Ricostruire una sequenza aritmetica


23

Data una sequenza aritmetica finita di numeri interi positivi con alcuni termini rimossi dal centro, ricostruire l'intera sequenza.

L'obiettivo

Considera una sequenza aritmetica: un elenco di numeri interi positivi in ​​cui la differenza tra due elementi successivi è la stessa.

2 5 8 11 14 17

Supponiamo ora che uno o più numeri interi vengano rimossi dalla sequenza, soggetti ai seguenti vincoli:

  • I numeri interi rimossi saranno termini consecutivi della sequenza.
  • Il primo e l'ultimo numero intero nella sequenza non verranno rimossi.
  • Almeno tre numeri interi rimarranno nella sequenza.

Per la sequenza sopra, le possibili rimozioni includono:

2 5 8 14 17  (removed 11)
2 5 17       (removed 8 11 14)
2 14 17      (removed 5 8 11)

Il tuo compito: data una di queste sequenze parziali, ricostruisci la sequenza completa originale.

Dettagli

Si può presumere che l'input sia valido (ha una soluzione) e manca almeno un termine. Tutti i numeri nella sequenza saranno numeri interi positivi (> 0). La sequenza può avere una differenza positiva o negativa tra i termini (cioè può essere in aumento o in diminuzione). Non sarà una sequenza costante (ad es 5 5 5.).

La tua soluzione può essere un programma completo o una funzione . Qualsiasi metodo di input e output predefinito è accettabile.

L'input e l'output possono essere una stringa (con qualsiasi delimitatore ragionevole), un elenco di stringhe o un elenco di numeri. Puoi rappresentare i numeri in qualunque base sia conveniente per la tua lingua.

Indica eventuali metodi / formati I / O insoliti nel tuo invio, in modo che altri possano testare il tuo codice più facilmente.

Casi test

In: 2 5 8 14 17
Out: 2 5 8 11 14 17
In: 2 5 17
Out: 2 5 8 11 14 17
In: 2 14 17
Out: 2 5 8 11 14 17
In: 21 9 6 3
Out: 21 18 15 12 9 6 3
In: 10 9 5
Out: 10 9 8 7 6 5
In: 1 10 91 100
Out: 1 10 19 28 37 46 55 64 73 82 91 100

Questo è ; vince la risposta più breve in ogni lingua.



Sarebbe stato interessante avere l'input nel modulo2 5 ... 17
— schnaader,

Risposte:


9

Haskell , 63 byte

f(a:b:c)|s<-[a,b..last c],all(`elem`s)c=s
f a=r$f$r a
r=reverse

Provalo online!

Fondamentalmente funziona cercando di costruire il risultato dalla parte anteriore e, se ciò fallisce, dalla parte posteriore. Questo utilizza il fatto che il primo e l'ultimo membro dell'input saranno sempre corretti, il fatto che i membri eliminati debbano essere consecutivi e il fatto che ci saranno sempre almeno tre elementi nell'input. Tutto quello che devo fare è presumere che il secondo o il penultimo membro siano accurati e controllino se funziona. Fortunatamente Haskell ha una sintassi davvero bella per la creazione di serie aritmetiche.

EDIT: grazie a @xnor per aver segnalato un bug e fornito una soluzione!


5
Anche se questo è carino, sembra che non funzioni sempre: [1,3,4,5]dà [1,3,5].
— xnor

1
E penso che all(`elem`s)cdovrebbe risolverlo con lo stesso numero di byte.
— xnor

6

05AB1E , 9 8 byte

Ÿs¥¿Äô€н

Provalo online!

Spiegazione

  • Costruisci l'intervallo [primo, ..., ultimo] con una differenza di +/- 1
  • Calcola i delta dell'input
  • Ottieni il valore assoluto del gcd dei delta
  • Dividi l'intera gamma in blocchi di quella dimensione
  • Ottieni il primo elemento di ogni blocco

Salvato 1 byte utilizzando gcd of deltasinvece di min delta, ispirato a user202729


5

Brachylog v2, 9 byte

⊆.s₂ᵇ-ᵐ=∧

Provalo online!

Questa è una presentazione di funzione. L'interprete Brachylog può essere fatto per valutare una funzione come se fosse un programma completo dandogli Zcome argomento da riga di comando; in questo caso, l'ingresso viene specificato nel formato, ad es. [1, 2, 4]e l'output viene restituito in un formato simile, ad es Z = [1, 2, 3, 4]. (Naturalmente, per l'invio di una funzione, l'input e l'output non sono in alcun formato; sono solo elenchi.)

Questo in realtà risolve un problema più difficile di quello richiesto dall'OP: risolve la sequenza aritmetica più breve di numeri interi che contengono i valori specificati nell'ordine specificato, indipendentemente dal fatto che le eliminazioni siano consecutive o meno. Poiché utilizza la forza bruta, può essere molto lento se vengono eliminati molti valori.

Spiegazione

Il programma ha tre parti principali.

⊆trova una supersequenza dell'input (ovvero una sequenza che ha l'input come sottosequenza). Quando c'è più di un possibile output da un programma Brachylog, l'output scelto è il primo output in ordine di tiebreak e l'ordine di tiebreak è determinato dal primo comando nel programma che ha un'opinione su di esso; in questo caso, ⊆specifica un ordine che favorisce output brevi rispetto a quelli lunghi. Quindi l'output che otterremo sarà la supersequenza più breve dell'input che obbedisce alle restrizioni nel resto del programma.

.... ∧viene utilizzato per generare il valore che vede come input (ovvero la supersequenza in questo caso), ma anche per affermare che una condizione specifica è valida. In altre parole, stiamo emettendo la supersequenza più breve che obbedisce a una condizione specifica (e ignorando qualsiasi risultato intermedio usato per vedere se obbedisce alla condizione).

Infine, abbiamo s₂ᵇ-ᵐ =, cioè "tutti i delta della sequenza sono uguali", la condizione che stiamo applicando all'output. (Il valore di ritorno da questo è un elenco di delta, piuttosto che la supersequenza stessa, motivo per cui abbiamo bisogno del .... ∧per garantire che venga prodotta la cosa giusta.)

Brachylog viene trattenuto qui non avendo alcun builtin in grado di gestire il calcolo di delta, applicando un'operazione a coppie sovrapposte da un elenco o simili. Invece, dobbiamo dire cosa intendiamo esplicitamente: s₂ᵇtrova all ( ᵇ) sottostringhe ( s) di lunghezza 2 ( ₂) (l'uso di ᵇè necessario per mantenere un collegamento tra incognite nelle sottostringhe e nella supersequenza; il più comunemente usato ᶠromperà questo link). Quindi -ᵐesegue una sottrazione su ciascuna di queste coppie per produrre un delta. È fastidioso dover scrivere cinque byte s₂ᵇ-ᵐper qualcosa per cui la maggior parte delle lingue moderne del golf ha una base, ma immagino che sia così che va il codegolf a volte.


4

Python 2, 104 97 89 83 71 67 60 byte

Grazie a Chas Brown per aver salvato 4 byte.
Grazie a ovs per il salvataggio di 7 byte.

Immettere l'elenco per argomenti.

lambda a,b,*c:range(a,c[-1],min(b-a,c[0]-b,key=abs))+[c[-1]]

Provalo online!

Spiegazione:

Poiché i rimossi sono consecutivi, è sufficiente verificare le differenze tra due coppie di elementi consecutivi.


È possibile salvare 3 byte sostituendoli b if b%c else ccon [c,b][b%c>0].
— Chas Brown,

@ChasBrown Grazie, anche se presto ho trovato un approccio migliore.
— Colera,

1
Bello con il key=abs! Sembra che da queste f=parti le persone spesso omettano la parte a meno che non venga utilizzata una funzione ricorsiva; così puoi salvare 2 byte in quel modo.
— Chas Brown,

1
Inoltre, sostituisci a[-1]-a[-2]con a[2]-a[1]: la logica è la stessa e otterrai altri 2 byte.
— Chas Brown,


4

Pyth , 11 byte

%hS.+SQ}hQe

Provalo qui!

Grazie a Steven H. per aver salvato un byte!

Pyth , 12 byte

%.aiF.+Q}hQe

Provalo qui!

Come funziona

% .aiF. + Q} hQe ~ Programma completo.

     . + Q ~ Ottieni i delta.
   iF ~ Riduzione di GCD.
 .a ~ Valore assoluto.
% ~ Modulare. Ottieni ogni ennesimo elemento di ...
        } ~ L'intervallo numerico compreso tra ...
         hQ ~ Il primo elemento e ...
           e ~ L'ultimo elemento.

Presort in Qmodo da poter ordinare e prendere il primo elemento anziché abs(GCD(Q))come in %hS.+SQ}hQeper 11 byte. Test suite
— Steven H.

3

Gelatina , 8 byte

ṂrṀmIg/$

Provalo online!

Gli appunti:

  • Funziona solo su una vecchia versione di Jelly. ( ad esempio questo commit ) (dove guse fractions.gcd, che hanno il segno di risultato uguale al segno di input, invece di math.gcd, che restituiscono sempre un valore positivo).

  • Il link TIO sopra è il link TIO Python 3, il codice Python è costituito dal codice sorgente Jelly dal commit che ho menzionato sopra, ad eccezione di tutto (3 file) impacchettato nello stesso file (per l'esecuzione di TIO) ed dictionary.pyè stato ridotto a solo alcune righe. Tuttavia dictionary.pynon è correlato a questa risposta, in quanto non utilizza una stringa compressa. (il “...»costrutto)

Spiegazione:

Innanzitutto, poiché viene eliminato un segmento continuo e rimangono almeno 3 elementi, rimangono due numeri consecutivi nella vecchia lista e i delta saranno tutti multipli del passaggio. Pertanto l' elenco gcddelle differenze ( I, incrementi) sarà il valore assoluto del passaggio.

Fortunatamente il segno gcdè firmato (vedi nota sopra)

Quindi il programma fa:

ṂrṀ

Un intervallo intero crescente dall'intimo Ṃal Ṁmassimo.

m

Modulare, scegli ogni ennesimo elemento.

Ig/$

Combinazione di $catene Monadic ( ) I(incrementi, differenze) e g/(riduzione degli gcdelementi dell'elenco). Se gli incrementi sono positivi, allora gcdsarà positivo e l'elenco di ritorno sarà da sinistra a destra (crescente) e viceversa.


Sìì! Batte la risposta 05AB1E di 1 byte!
— user202729

Usando gcdinvece di minfarci legare. Peccato che ottenga un gcd con segno, altrimenti sarei alle 7;)
— Emigna il

3

MATL , 13 byte

1)0GdYkG0)3$:

Provalo online!

Spiegazione:

Consider the example input [2 14 17]:
           # implicit input, STACK: [[2 14 17]]
1)         # push 1, index, STACK: [2]
0G         # push 0, duplicate input, STACK: [2, 0, [2 14 17]]
d          # take differences, STACK: [2, 0, [12, 3]]
Yk         # get value in [12, 3] nearest to 0, STACK: [2, 3]
G0)        # get last element in input, STACK: [2, 3, 17]
3$:        # 3-input :, computes 2:3:17, the range from 2 to 17 by 3
           # STACK: [[2 5 8 11 14 17]], implicit output.


3

JavaScript (ES6), 92 90

Modifica 2 byte salvati grazie ad Arnauld

Facile, in quanto è sufficiente verificare le differenze tra i primi due e gli ultimi due. Ma ancora incredibilmente lungo.

s=>(e=(z=s.pop(a=s[0]))-s.pop(d=s[1]-a),[...Array((z-(a-=d=e*e>d*d?d:e))/d)].map(_=>a+=d))

Meno golf

s=>{
  a =s[0]
  b =s[1]
  z = s.pop()
  y = s.pop()
  d = b-a
  e = z-y
  d = e*e>d*d?d:e  
  n = (z-a)/d+1
  return [...Array(n)].map((_,i) => a + i*d)
}

Test

var F=
s=>(e=(z=s.pop(a=s[0]))-s.pop(d=s[1]-a),[...Array((z-(a-=d=e*e>d*d?d:e))/d)].map(_=>a+=d))

var test=`In: 2 5 8 14 17 Out: 2 5 8 11 14 17
In: 2 5 17 Out: 2 5 8 11 14 17
In: 2 14 17 Out: 2 5 8 11 14 17
In: 21 9 6 3 Out: 21 18 15 12 9 6 3
In: 10 9 5 Out: 10 9 8 7 6 5
In: 1 10 91 100 Out: 1 10 19 28 37 46 55 64 73 82 91 100`.split`\n`
.map(r=>r.split`Out`.map(x=>x.match(/\d+/g)))

test.forEach(([i,k])=>{
  var o=F(i.slice(0))
  var ok = o+''==k
  console.log(ok?'OK':'KO',i+' => '+o)
})


a-=d=e*e>d*d?d:edovrebbe funzionare e salvare 2 byte.
— Arnauld,

@Arnauld funziona davvero grazie
— edc65

2

Wolfram Language (Mathematica) , 50 byte

Range[#&@@#,#[[-1]],#&@@Differences@#~SortBy~Abs]&

Provalo online!


Un "elenco di numeri" include avere i numeri come singoli argomenti? In tal caso, sembra che potresti risparmiare un buon numero di byte.
— numbermaniac

@numbermaniac Non credo, dal momento che non esiste un built-in che recupera l'ultimo input ...
— JungHwan Min

Ahh ... vero. Dimenticato quello.
— numbermaniac

Puoi usarlo {##}e Last@{##}il massimo che ho potuto ottenere è stato di 51 byte.
— numbermaniac


1

Haskell , 73 69 byte

f(h:t)=do(#)<-[(-),(+)];[h,h#minimum(abs<$>zipWith(-)t(h:t))..last t]

Provalo online!


1
Ho trovato una soluzione a 63 byte ma è abbastanza diversa dalla tua. Devo fare un post separato?
— user1472751

@ user1472751 Non sono Laikoni, ma questo sito era destinato alla competizione e alla collaborazione. Quindi l'avrei pubblicato.
— H.Piz,

@ user1472751 Bel approccio! Vai avanti e pubblicalo come risposta personale.
— Laikoni,

1

J , 49, 47 46 byte

(0-[:<./2|@-/\]){.@[&]\({.<.{:)+[:i.{:(+*)@-{.

Ispirato alla soluzione di Emigna.

Come funziona:

 (0-[:<./2|@-/\]){.@[&]\({.<.{:)+[:i.{:(+*)@-{. - fork of 3 verbs

                        ({.<.{:)+[:i.{:(+*)@-{. - generates a list in the entire range of values
                                     {:     -{. - last minus first element  
                                       (+*)@    - adds the signum of the difference
                                 [:i.           - makes a list 
                       ({.<.{:)                 - the smallest of first and last elements                                     
                               +                - adds the offset to the list (translates all elements according to the first one)

 (0-[:<./2|@-/\])                               - finds the step
         2|@-/\]                                - the absolute differences between all consecutive elements
    [:<./                                       - the smallest one
  0-                                            - negate (for splitting)

                 {.@[&]\                        - splits the list from the right verb into left verb's result sublists and takes their first elements

Provalo online!


1

Buccia , 9 byte

m←C▼Ẋ≠⁰…⁰

Provalo online!

Grazie mille a H.PWiz per aver dimezzato il conteggio dei byte, indicando che l'applicazione …su un elenco lo diversifica! ...


@ HP.Wiz X_X Non sapevo che Husk elencasse intervalli del genere ... Sei sicuro di non voler pubblicarlo come risposta separata?
— Mr. Xcoder,

@ HP.Wiz Grazie un loooot !
— Mr. Xcoder,

Inoltre, può F⌋essere sostituito da ▼?
— H.Piz,

@ H.PWiz @ _ @ Perché funziona?
— Mr. Xcoder,

La differenza più piccola (assoluta) sarà la differenza originale. L'unico motivo gcdera di affrontare i delta negativi
— H.Pwiz,

1

C # (.NET Core) , 167 + 13 = 180 145 + 13 = 158 byte

a=>{int x=a[1]-a[0],y=a[2]-a[1],d=x*x<y*y?x:y,s=Math.Abs((a[a.Length-1]-a[0])/d),i=0,j=a[0];var r=new int[s+1];for(;i<=s;j+=d)r[i++]=j;return r;}

Provalo online!

+13 per using System;

Sorprendentemente, questa sfida aveva più sfumature di quanto inizialmente previsto.

Ringraziamenti

-22 byte salvati grazie ad alcune semplici semplificazioni di @DLosc.

DeGolfed

a=>{
    int x = a[1]-a[0],        // difference between first and second numbers
        y = a[2]-a[1],        // difference between second to last and last numbers
        d = x*x < y*y? x : y, // smallest absolute value difference
        s = Math.Abs((a[a.Length-1] - a[0]) / d), // number of steps in the reconstructed sequence (not the number of elements)
        i = 0,                // step position
        j = a[0];             // next number in reconstructed sequence

    var r = new int[s+1];

    // reconstruct the sequence
    for(; i <= s; j+=d)
        r[i++]=j;

    return r;
}

0

Python 2 , 147 byte

from fractions import*
a=input()
b=[j-i for i,j in zip(a[:-1],a[1:])]
l=min(gcd(i,j)for i in b for j in b)
print list(range(a[0],a[-1]+l/abs(l),l))

Provalo online!





0

Japt , 12 byte

ÌõUg Uäa ñ g

Provalo


Spiegazione

Genera un array di numeri interi ( õ) dall'ultimo elemento dell'array di input ( Ì) al primo ( Ug). Calcola il passaggio tra gli elementi ottenendo tutte e due le coppie di elementi dall'input e riducendole per differenza assoluta ( Uäa) quindi ordinando ( ñ) quell'array e prendendo il primo elemento ( g).

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.