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][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.