Questo numero è triangolare?


33

Sfida

Dato un numero intero positivo, determinare se si tratta di un numero triangolare e, di conseguenza, emettere uno dei due valori costanti e distinti.

Definizione

UN numero triangolare è un numero che può essere espresso come la somma di numeri interi positivi consecutivi, a partire da 1. Possono anche essere espressi con la formula n(n + 1) / 2, dove nè un numero intero positivo.

Casi test

Truthy:

1
3
6
10
15
21
55
276
1540
2701
5050
7626
18915
71253
173166
222111
303031
307720
500500
998991

Falsy:

2
4
5
7
8
9
11
16
32
50
290
555
4576
31988
187394
501500
999999

Regole

  • La tua voce può essere una funzione o un programma.
  • Si può presumere che l'input sia un numero intero positivo inferiore a 10 6 .
  • È necessario selezionare due output costanti e distinti per distinguere le due categorie.

Questo è , quindi vince il codice più breve in byte in ogni lingua.





Perché non hai incluso zero?
Neil,

1
@Neil Volevo minimizzare il numero di possibili casi limite, e gestire zero è uno di quelli che ho ritenuto non troppo importante. Pensi che sarebbe stato meglio se fosse necessario gestire lo zero? (La risposta di Jelly attualmente non riesce a zero, per esempio)
ETHproductions

Risposte:


21

Haskell , 23 byte

MODIFICARE:

  • -1 byte: @xnor si è sbarazzato delle parentesi con a $.

Una funzione anonima che accetta Inte restituisce aChar .

L'output è '1'per numeri triangolari e '0'per altri.

(!!)$show.(10^)=<<[0..]

Provalo online!

  • Usare come ((!!)$show.(10^)=<<[0..]) 998991 .
  • Genera i numeri 1, 10, 100, 1000, ..., li converte in stringhe e li concatena. Quindi si indicizza nella stringa infinita risultante

    "1101001000100001000001000000...

6
Un metodo fantasioso! È possibile salvare un byte con (!!)$show.(10^)=<<[0..].
xnor

20

Python , 24 byte

lambda n:(8*n+1)**.5%1>0

Provalo online!

Uscite Falseper numeri triangolari, Trueper il resto. Verifica se 8*n+1è un quadrato perfetto. Python prenderà i quadrati perfetti per ottenere float interi, non importa quanto grandi, quindi non ci sono problemi in virgola mobile.


3
(1<<10000)**.5: OverflowError: int troppo grande per convertire in float
isaacg

@isaacg La sfida non richiede input così grandi: "Puoi supporre che l'input sia un numero intero positivo inferiore a 10 ^ 6"
trichoplax,

1
@trichoplax Penso di aver contestato l'affermazione di xnor nel testo. La presentazione va bene, sono d'accordo.
isaacg,

13

Gelatina , 4 byte

R+\ċ

Provalo online!

Come?

R+\ċ - Main link: n
R    - range(n)   -> [1,2,3,...,N]
  \  - cumulative reduce by:
 +   -   addition -> [1,3,6,...,T(N)]
   ċ - count occurrences of right (n) in left -> 1 if triangular, 0 otherwise

Sono sorpreso che la riduzione cumulativa non raggiunga automaticamente un intervallo. C'è una scelta progettuale dietro questo?
ETHproductions

Non ne sono sicuro al 100%, ma penso che (almeno al momento) occorrerebbe ridurre l'operazione diadica per provocare un intervallo.
Jonathan Allan,

... in realtà anche quello non sembra applicarsi (ad esempio questo vs questo . Sembra che l'implementazione del collegamento rapido abbia la precedenza in modo tale che l'iterabile non faccia un intervallo anche se l'operazione diadica lo definisce per farlo per un argomento. Pinged Dennis al campo questo :)
Jonathan Allan,

@ETHproductions /e \probabilmente sono stati tra i primi cinque rapidi ad essere implementati, predando l'idea di lanciare argomenti interi da spaziare.
Dennis,

13

Retina , 10 byte

(^1|1\1)+$

L'input è in unario. L'output è 0o 1.

Provalo online! (Come una suite di test che esegue la conversione da decimale a unaria per comodità.)

Spiegazione

Questo è l'esercizio più basilare nei riferimenti diretti. La maggior parte delle persone ha familiarità con i riferimenti alle regex, ad es(.)\1 per abbinare un personaggio ripetuto. Tuttavia, alcuni degli aromi più avanzati consentono di utilizzare un backreference prima o all'interno del gruppo a cui si riferisce. In tal caso, di solito viene chiamato riferimento in avanti. Questo può avere senso se il riferimento viene ripetuto. Potrebbe non essere ben definito nella prima iterazione, ma nelle iterazioni successive, il gruppo successivo o circostante ha catturato qualcosa e può essere riutilizzato.

Questo è più comunemente usato per implementare modelli ricorrenti su stringhe unarie. In questo caso, proviamo a far corrispondere l'input come la somma di numeri interi consecutivi:

(        # This is group 1, which we'll repeat 1 or more times.
  ^1     #   Group 1 either matches a single 1 at the beginning of the string.
|        # or
  1\1    #   It matches whatever the previous iteration matched, plus another
         #   1, thereby incrementing our counter.
         # Note that the first alternative only works on the first iteration
         # due to the anchor, and the second alternative only works *after*
         # the first iteration, because only then the reference is valid.
)+
$        # Finally, we make sure that we can exactly hit the end of the
         # string with this process.

1
Perché non (^|1\1)+$funziona?
Leaky Nun,

3
I motori regex di @LeakyNun hanno un'ottimizzazione che smettono di ripetere un gruppo se era vuoto n volte in cui n è il minimo del quantificatore che stai utilizzando (nel tuo caso 1; se il minimo fosse 0, verrebbe comunque provato una volta) . Se si modifica +in {2,}, dovrebbe funzionare. Questa ottimizzazione impedisce cicli infiniti, ma è anche l'unica cosa che impedisce a regex .NET di essere completamente completo.
Martin Ender,

Questo mi ha appena salvato 70 byte: codegolf.stackexchange.com/a/118387
Neil

Rendi 74 byte, grazie a \G!
Neil,


8

Mathematica, 16 byte

OddQ@Sqrt[1+8#]&

Essenzialmente una porta della soluzione Python di xnor . Uscite Trueper numeri triangolari, Falsealtrimenti.


7

JavaScript (ES6), 30 27 byte

Salvato 2 byte grazie a kamoroso94

f=(n,k)=>n>0?f(n+~k,-~k):!n

Casi test

Versione non ricorsiva (ES7), 19 byte

La risposta del porto di Adnan .

x=>(8*x+1)**.5%1==0

Solo vedendo ora che hai modificato la soluzione a 19 byte nella tua risposta qualche minuto prima di pubblicare la mia . Devo cancellare il mio? Qual è l'etichetta generalmente accettata su questo?
Shaggy,

1
@Shaggy Non penso che sia un vero problema qui. La mia risposta "principale" è davvero quella ricorsiva.
Arnauld,

Ridurre a 28 byte con f=(n,k=1)=>n>0?f(n-k,k+1):!n?
kamoroso94,

1
@ kamoroso94 Grazie! Aggiornato. E un terzo byte è stato salvato omettendo l'inizializzazione di k.
Arnauld,

Uso elegante di bit a bit NOT come incrementatore per un undefinedvalore iniziale ; la tua modifica è stata un piacere leggere dopo che sono arrivato autonomamente alla tua soluzione precedente.
apsillers,

6

CJam , 11 byte

ri2*_mQ_)*=

Uscite 1 per triangolare, 0altrimenti.

Provalo online!

Spiegazione

Considera l'input 21.

ri               e# Input integer.             STACK: 21
  2*             e# Multiply by 2.             STACK: 42
    _            e# Duplicate.                 STACK: 42, 42
     mQ          e# Integer square root.       STACK: 42, 6
       _)        e# Duplicate, increment.      STACK: 42, 6, 7
         *       e# Multiply.                  STACK: 42, 42
          =      e# Equal?                     STACK: 1

6

Brain-Flak , 40 byte

(([{}](((()))<>))<>){<>({}({}({})))}{}{}

Wheat Wizard e io abbiamo avuto un duello su questa domanda. Quando decidemmo di pubblicare le nostre soluzioni eravamo legati a 42 byte, ma trovai un golf a 2 byte della sua soluzione. Abbiamo deciso che contava come un pareggio (la mia soluzione è sotto).

Provalo online!

Spiegazione:

# Set up the stacks like this:  -input
                                     1     -input
                                     1          1
(([{}](((()))<>))<>)                 ^

# Output 1 for triangular and 0 for non-triangular 
{<>({}({}({})))}{}{}

Per una spiegazione completa, consultare la risposta del Mago del grano .


Brain-Flak , 42 byte

(([({})])<>){(({}())<>{}({})){((<>))}{}{}}

Uscite 0\n (letterale newline) per verità e stringa vuota per falsità.

L'idea è di sottrarre 1, poi 2 e 3 fino all'input. Se premi 0, sai che si tratta di un numero triangolare, quindi puoi fermarti qui.

Provalo online! (verità)
Provalo online! (falsy)

# Push -input on both stacks. One is a counter and the other is a running total
(([({})])<>)

# Count up from -input to 0
{
  # Push the new total which is: (counter += 1) + total (popped) + input (not popped)
  # This effectively adds 1, then 2, then 3 and so on to the running total
  (({}())<>{}({}))
  # If not 0
  {
    # Push to 0s and switch stacks to "protect" the other values
    ((<>))
  # End if
  }
  # Pop the two 0s, or empty the stack if we hit 0
  {}{}
# End loop
}

Ecco una soluzione a 46 byte che ho trovato interessante.

{<>(({}())){({}[()]<>{(<({}[()])>)}{}<>)}{}<>}

Uscite 0\n (letterale newline) per verità, la stringa vuota per falsità.

L'idea è di fare il conto alla rovescia dall'input in base a numeri consecutivi, 1 alla volta. Es input - (1) - (1,1) - (1,1,1). Ogni volta che sottraggiamo, se non siamo ancora a 0, lasciamo un valore extra nello stack. In questo modo, se siamo a 0 e stiamo ancora sottraendo quando pop, rimuoviamo l'ultimo valore nello stack. Se l'input era un numero triangolare, finiremo esattamente a 0 e non faremo apparire lo 0.

Provalo online! verità
Provalo online! falsy

# Implicit input (call it I)

# Until we reach 0, or the stack is empty
{
  # Add 1 to the other stack and push it twice. This is our counter.
  <>(({}()))
  # While counter != 0
  {
    # counter -= 1
    ({}[()]
    # if I != 0 
    <>{
      # I -= 1, and push 0 to escape the if
      (<({}[()])>)
    # End if
    }
    # Pop from the stack with I. This is either the 0 from the if, or I
    {}
    # Get ready for next loop End while
    <>)
  # End While
  }
  # Pop the counter that we were subtracting from
  {}<>
# End Until we reach 0, or the stack is empty.
}

6

Gelatina , 5 byte

×8‘Ʋ

Provalo online!

sfondo

Sia n l'input. Se n è il k esimo numero triangolare, abbiamo

n=k(k+1)2k2+k2n=0k=12(1±1+8n),

il che significa che ci sarà una soluzione naturale se e solo se 1 + 8n è un quadrato strano e perfetto. Chiaramente, controllando la parità di 1 + 8n non è necessario .

Come funziona

×8‘Ʋ  Main link. Argument: n

×8     Yield 8n.
  ‘    Increment, yielding 8n + 1.
   Ʋ  Test if the result is a perfect square.

5

PowerShell , 31 30 byte

"$args"-in(1..1e6|%{($s+=$_)})

Provalo online!

Metodo della forza bruta piacevole e lento. Crea una matrice di ogni somma da 1 a 10 6 e vedi se l'argomento è presente.


5

Brain-Flak , 42 byte

(([{}](<((())<>)>))<>){<>({}({}({})))}{}{}

Provalo online!

Spiegazione

L'obiettivo di questo programma è quello di creare uno stato su due stack ed eseguire operazioni costanti su entrambi gli stack fino a quando uno di essi è zero, quindi possiamo produrre in base allo stack su cui ci troviamo. Questo è simile ai programmi che determinano il segno di un numero. Questi programmi mettono nsu uno stack e-n sull'altro e ne aggiungono uno e cambiano stack fino a quando uno degli stack è zero. Se il numero era negativo in primo luogo, il primo stack raggiungerà lo zero, se il numero fosse positivo, l'altro stack raggiungerà lo zero.

Qui creiamo due stack uno che sottrae numeri consecutivi dall'input e uno che sottrae solo uno. Quello che sottrae i numeri consecutivi terminerà solo se il numero è triangolare (altrimenti, passerà solo zero e continuerà ad andare verso i negativi). L'altro terminerà sempre per qualsiasi numero positivo, ma lo farà sempre più lentamente del primo, quindi i numeri non triangolari termineranno su quello stack.

Quindi, come possiamo impostare stack in modo che la stessa operazione sottrae numeri consecutivi su uno e sottrae uno sull'altro? Su ogni stack abbiamo l'input in cima in modo che possa essere verificato in, sotto che abbiamo la differenza e sotto che abbiamo la differenza della differenza. Ogni volta che eseguiamo aggiungiamo la "differenza della differenza" alla normale "differenza" e la sottraggiamo dall'input. Per lo stack che controlla la triangolarità impostiamo la nostra doppia differenza in 1modo tale da ottenere numeri interi consecutivi ogni volta che eseguiamo, per l'altro stack lo impostiamo in 0modo da non cambiare mai la differenza, ovvero rimane sempre 1. Ecco come è impostato lo stack all'inizio, dov'è nl'input:

-n  -n
 0   1
 1   0

Quando alla fine terminiamo, possiamo usare queste differenze per controllare su quale stack siamo, pop i primi due valori e otteniamo 1un numero triangolare e 0un numero non triangolare.


Codice annotato

(([{}](<((())<>)>))<>) Set up the stack
{                      While
 <>                    Switch stacks
 ({}({}({})))          Add bottom to second to bottom, add second to bottom to top
}                      End while
{}{}                   Pop the top two values

Ecco una soluzione da 50 byte che mi piace anche.

{(({}[()]))}(([[]])<>){({}{}())<>}({}{()<><{}>}{})

Provalo online!


5

Cubix , 23 24 25 byte

I1Wq/)s.;0..s;p-?\.+O@u

0 per verità e niente 0 per falsità. Bruta le forze aumentando il contatore, aggiungendo alla somma cumulativa e confrontando con l'input. Ora prova a inserirlo in un cubo 2x2x2. Fatto!

    I 1
    W q
/ ) s . ; 0 . .
s ; p - ? \ . +
    O @
    u .

Provalo online!

  • / Riflettere per affrontare.
  • I10\ ottenere l'input intero, premere 1 (contatore), premere 0 (somma) e riflettere
  • +s;p-corpo ad anello. Aggiungi somma e contatore, elimina somma precedente, aumenta input e sottrai
  • ? Prova il risultato della sottrazione
    • Per 0 risultati, proseguire dritto \.uO@riflette su faccia inferiore, no-op, inversione a U, uscita e arresto.
    • Per un risultato positivo, girare a destra sulla faccia inferiore e @fermarsi
    • Per risultati negativi, girare la ;qWs)/susottrazione di rilascio a sinistra , mettere l'input in basso, spostare a sinistra, scambiare contatore e somma, incrementare contatore, riflettere, scambiare somma e contatore, inversione a U sul corpo del circuito principale.

Così incredibilmente vicino ... che l'ultimo byte richiederà molto sforzo e intelligenza.
ETHproductions

Sì, pensavo di averlo ma è inafferrabile
MickyT

1
@ETHproductions ha trovato il byte
MickyT

Il tuo codice e il tuo cubo spiegato sembrano essere diversi, l'angolo in basso a destra è a .sul cubo ma a 1nel tuo codice.
Wheat Wizard

@WheatWizard Grazie, cattivo montaggio da parte mia
MickyT

4

05AB1E , 7 6 byte

EDIT : Grazie a @Dennis: ho salvato un byte perché mi sono dimenticato dell'operatore di incremento

8*>t.ï

Provalo online!

nè triangolare se sqrt(8n + 1)è un numero intero

Come funziona

8* # multiply implicit input by 8
  > # add one
   t # sqrt
    .ï # is integer

Probabilmente non era ancora disponibile al momento, ma t.ïpuò essere in Ųquesti giorni, che è un builtin per verificare se un numero è un quadrato.
Kevin Cruijssen,

4

Perl 6 , 17 byte

{$_∈[\+] 1..$_}

Controlla solo se $_, l'input per la funzione, è uguale a uno qualsiasi degli elementi della riduzione triangolare dell'addizione (1, 1+2, ..., 1+2+...+$_).


4

Alice , 38 22 byte

Molti byte salvati grazie a Martin e Leo

/ i \ 2 * .2RE.h * -n / o @

C'è una nuova riga finale. Uscite 1per triangolare, 0altrimenti.

Provalo online!

Spiegazione

Questo utilizza lo stesso approccio della mia risposta CJam , solo più maldestro . In forma linearizzata, il programma diventa

i2*.2RE.h*-no@

dove ie osono in realtà in modalità ordinale.

Considera l'input 21come esempio.

i         Input integer                       STACK: 21
2*        Multiply by 2                       STACK: 42
.         Duplicate                           STACK: 42, 42
2RE       Integer square root                 STACK: 42, 6
.         Duplicate                           STACK: 42, 6, 6
h         Increment                           STACK: 42, 6, 7
*         Multiply                            STACK: 42, 42
-         Subtract                            STACK: 0
n         Logical negation                    STACK: 1
o         Output integer                      STACK:
@         End program

La mia prima risposta di Alice
Luis Mendo,

1
Ho la sensazione che questo potrebbe essere dimezzato con una delle fantasiose strutture di controllo di Martin ...
ETHproductions

Anch'io ... :-)
Luis Mendo,

Il mio primo golf Alice: stesso codice, 23 byte
Nitrodon

Un layout più "standard" per questo tipo di programma sarebbe questo . Detto questo, potresti sbarazzarti dell'1 nello stack e semplicemente emettere la logica negazione della sottrazione (cioè ...h*-no@)
Leone,

4

Japt , 10 7 byte

Salvato 3 byte grazie a @Luke e @ETHproductions

*8Ä ¬v1

Provalo online!

Spiegazione:

*8Ä ¬v1
    ¬    // Square root of:
*8       //   Input * 8
  Ä      //   +1
     v1  // Return 1 if divisible by 1; Else, return 0

õ å+ øU

Spiegazione:

õ å+ øU
õ           // Create a range from [1...Input]
  å+        // Cumulative reduce by addition
     øU     // Does it contain the input?

Provalo online!


La domanda richiede due uscite distinte e costanti.
xnor

*8Ä ¬u1 cper 9B (uscite 0 se l'ingresso è triangolare, 1 altrimenti)
Luca

@Luke Potresti passare u1 ca v1, credo (commutazione delle uscite)
ETHproductions

7 byte? Bello! In qualche modo è mancato questo mentre pubblicavo la mia soluzione simile alla fine dello scorso maggio. Fammi sapere se desideri che lo elimini.
Shaggy,

4

R , 23 19 byte

Approccio simile alle altre risposte. Verifica se 8x+1è un quadrato perfetto.
-4 byte grazie Giuseppe e MickyT.

!(8*scan()+1)^.5%%1

Provalo online!


2
puoi usare !invece di==0
Giuseppe il

Questo è molto più bello dato che è anche vettoriale!
Giuseppe,

1
Penso che puoi sbarazzarti anche delle staffe esterne!(8*scan()+1)^.5%%1
MickyT

3

MATL , 5 byte

t:Ysm

Provalo online!

Spiegazione:

t       % Duplicate input
 :      % Range(1, input)
  Ys    % Cumulative sum. This will push the first *n* triangular numbers
    m   % ismember. Pushes true if the input is contained within the array we just pushed

Stavo per postare t:Ys=a. Dimenticato m:-)
Luis Mendo,

1
@LuisMendo di cui non sapevo mfino a quando non ho visto questa risposta . Divertente come le due risposte siano quasi identiche: D
DJMcMayhem

3

Lotto, 72 byte

@set/aj=i=0
:l
@if %1% gtr %j% set/aj+=i+=1&goto l
@if %1==%j% echo 1

Emette 1 in caso di successo, niente in caso di fallimento. Funziona anche per zero, anche se non richiesto dalla domanda per qualche motivo.


3

JavaScript (ES7), 19 18 byte

Dalla mia risposta a una domanda correlata .

Uscite falseper numeri triangolari o truenon triangolari, come consentito dall'OP.

n=>(8*n+1)**.5%1>0

Provalo

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


Penso che potresti salvare un byte con n=>(8*n+1)**.5%1>0(che
rovescerebbe

@ETHproductions: OK, purché tu lo permetta. Farlo normalmente è permesso, però?
Shaggy,

1
Si qualifica come "due output costanti e distinti", quindi sì. Altre sfide al problema decisionale possono richiedere verità / falsità.
ETHproductions


3

Mathematica, 28 byte

!Accumulate@Range@#~FreeQ~#&

Consiglio di sostituirlo 7!con #. Innanzitutto, è più breve; ancora più importante, l'attuale soluzione non è corretta, poiché impone artificialmente un limite alla dimensione dell'input su cui lavora.
Greg Martin,

1
OP dice: "Puoi supporre che l'input sia un numero intero positivo inferiore a 10 ^ 6". Ma mi piace la tua idea e la prenderò, sebbene la mia dia il risultato giusto per ogni caso usando un elenco di 5040 elementi ma il tuo caso peggiore necessita di un elenco di 999999 elementi. Grazie per la punta!
J42161217,

1
Spiacenti, non ho visto il commento del PO! Sì, ci sono alcuni incentivi "perversi" nel golf di codice: che il risparmio di 1 byte è più importante in una domanda di code-golf rispetto a tutta l'efficienza del mondo :)
Greg Martin,


3

Eccellere, 31 22 byte

9 byte salvati grazie a Octopus

Uscite TRUEper numeri triangolari. Altrimenti FALSE. Verifica se 8*n+1è un quadrato perfetto.

=MOD(SQRT(8*B1+1),1)=0

1
=MOD(SQRT(8*A1+1),1)=0salva qualche byte
Polpo

2

Brachylog , 5 byte

≥ℕ⟦+?

Provalo online!

Spiegazione

≥ℕ⟦+?
≥ℕ     There is a number from 0 to {the input} inclusive
  ⟦    such that the range from 0 to that number
   +   has a sum
    ?  that equals the input


2

Python - 52 byte

Nota: so che le altre due risposte di Python sono molto più brevi, ma questa è la vecchia scuola, più che altro un algoritmo manuale

n=input();i=s=0
while s<n:s=(i*i+i)/2;i+=1
print s>n

2

APL (Dyalog) , 6 byte

⊢∊+\∘

Provalo online!

Spiegazione

⊢∊+\∘
                       Creates a range from 1 to the right_argument
  +\                    Cumulative sum of this range; 1 1+2 1+2+3 .. 1+2+..+n. These are the triangular numbers
⊢∊                      Does the right argument belong to this list of integers in this cumulative sum

Output 0per falso e 1vero.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.