Genera la sequenza di residui minima


21

Ogni numero può essere rappresentato usando una sequenza di resti infinitamente lunga. Ad esempio, se prendiamo il numero 7 ed eseguiamo 7mod2, quindi 7mod3, quindi 7mod4, e così via, otteniamo 1,1,3,2,1,0,7,7,7,7,.....

Tuttavia, abbiamo bisogno della sottosequenza residua più breve possibile che può ancora essere utilizzata per distinguerla da tutti i numeri inferiori. Usando di nuovo 7, [1,1,3]è la sottosequenza più breve, perché tutte le sottosequenze precedenti non iniziano con [1,1,3]:

0: 0,0,0,0...
1: 1,1,1,1...
2: 0,2,2,2...
3: 1,0,3,3...
4: 0,1,0,4...
5: 1,2,1,0...
6: 0,0,2,1...

Si noti che [1,1] non funziona per rappresentare 7, perché può anche essere usato per rappresentare 1. Tuttavia, è necessario eseguire l'output [1]con un input di 1.

Input Output

Il tuo input è un numero intero non negativo. È necessario generare una sequenza o un elenco della sequenza di residui di lunghezza minima come definito sopra.

Casi test:

0: 0
1: 1
2: 0,2
3: 1,0
4: 0,1
5: 1,2
6: 0,0,2
7: 1,1,3
8: 0,2,0
9: 1,0,1
10: 0,1,2
11: 1,2,3
12: 0,0,0,2
30: 0,0,2,0
42: 0,0,2,2
59: 1,2,3,4
60: 0,0,0,0,0,4
257: 1,2,1,2,5,5
566: 0,2,2,1,2,6,6
1000: 0,1,0,0,4,6,0,1
9998: 0,2,2,3,2,2,6,8,8,10
9999: 1,0,3,4,3,3,7,0,9,0

Ecco le prime 10.000 sequenze , nel caso tu sia interessato (i numeri di riga sono disattivati ​​di 1).

Questo è un , quindi rendilo il più corto possibile nella tua lingua preferita. Punti bonus falsi per tutte le risposte veloci!



@nimi ne abbiamo parlato in chat e ho deciso che le sequenze devono essere lunghe almeno 1 elemento.
Nathan Merrill,

1
Sono un po 'sorpreso che non l'abbia limitato ai resti primi.
Neil,

Va bene se l'output viene restituito in un elenco?
R. Kap,

@neil, l'ho anche considerato, ma poiché i resti sono diversi con i numeri compositi, ho votato per mantenerlo
Nathan Merrill

Risposte:


5

Mathematica, 60 53 byte

#~Mod~FirstCase[2~Range~#&/@Range[#+2],x_/;LCM@@x>#]&

Un po ' veloce (gestisce 10000 in ~ 0,1 secondi, ma probabilmente esaurirà la memoria per 100000).

Il codice genera un errore ma calcola il risultato correttamente.

Spiegazione

In chat abbiamo scoperto che i divisori richiesti possono sempre essere determinati come l'elenco più breve il {1, 2, ..., n}cui multiplo meno comune supera l'input. Un breve argomento del perché: se l'LCM è inferiore all'input, sottrarre l'LCM dall'input lascerebbe invariati tutti i divisori, quindi la rappresentazione non è unica. Tuttavia, per tutti gli input inferiori all'LCM, i resti saranno unici, altrimenti la differenza tra due numeri con resti uguali sarebbe un multiplo più piccolo di tutti i divisori.

Per quanto riguarda il codice ... come al solito l'ordine di lettura di Mathematica golf è un po 'divertente.

Range[#+2]

Questo ci fornisce un elenco [1, 2, 3, ..., n+2]per l'input n. Il +2è quello di garantire che funziona correttamente per 0ed 1.

2~Range~#&/@...

Mappa 2~Range~#(zucchero sintattico per Range[2,#]) su questo elenco, quindi otteniamo

{{}, {2}, {2,3}, ..., {2,3,...,n+2}}

Queste sono le liste dei divisori candidati (ovviamente in generale è molto più di quanto avremo bisogno). Ora troviamo il primo di essi il cui LCM supera l'input con:

FirstCase[...,x_/;LCM@@x>#]

Più sintassi: x_è un modello che corrisponde a qualsiasi elenco e lo chiama x. Il /;attribuisce una condizione di quel modello. Questa condizione è LCM@@x>#dove si @@ applica la funzione all'elenco, ovvero LCM@@{1,2,3}significa LCM[1,2,3].

Infine otteniamo semplicemente tutti i resti, facendo uso del fatto che Modè Listable, cioè si mappa automaticamente su un elenco se uno degli argomenti è un elenco (o se entrambi sono elenchi della stessa lunghezza):

#~Mod~...

5

Gelatina , 14 byte

‘Ræl\>iṠ2»2r⁸%

Questo utilizza il fatto che la soluzione (se presente) di un sistema di congruenze lineari è unica modulo LCM dei moduli. Provalo online! o verifica tutti i casi di test .

Come funziona

‘Ræl\>iṠ2»2r⁸%  Main link. Argument: n

‘               Increment; yield n+1.
 R              Range; yield [1, ..., n+1].
  æl\           Cumulatively reduce by LCM.
                This yields [LCM(1), ..., LCM(1, ..., n+1)].
     >          Compare all LCMs with n.
      iṠ        Find the first index of sign(n).
                This yields the first m such that LCM(2, ..., m) > n if n > 0, and
                0 if n == 0.
        2»      Take the maximum of the previous result and 2, mapping 0 to 2.
          2r    Yield the range from 2 up to and including the maximum.
            ⁸%  Compute n modulo each integer in that range.

5

MATL , 24 byte

Grazie a @nimi per aver segnalato un errore in una versione precedente di questa risposta (ora corretta)

Q:qtQ!\t0Z)tb=YpsSP2):Q)

Questo esaurisce la memoria nel compilatore online per i due casi di test più grandi (ma funziona su un computer con 4 GB di RAM).

Provalo online!

Spiegazione

Questo applica la definizione in modo semplice. Per l'input ncalcola un array 2D contenente mod(p,q)con pda 0a ne qda 1a n+1. Ciascuno pè una colonna e ciascuno qè una riga. Ad esempio, con input n=7questo array è

0 0 0 0 0 0 0 0
0 1 0 1 0 1 0 1
0 1 2 0 1 2 0 1
0 1 2 3 0 1 2 3
0 1 2 3 4 0 1 2
0 1 2 3 4 5 0 1
0 1 2 3 4 5 6 0
0 1 2 3 4 5 6 7

Ora l'ultima colonna, che contiene i resti di n, è un elemento saggio rispetto a ciascuna colonna di questo array. Questo cede

1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1
0 1 0 0 1 0 0 1
0 0 0 1 0 0 0 1
0 0 1 0 0 0 0 1
0 1 0 0 0 0 0 1
1 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1

dove 1indica l'uguaglianza. L'ultima colonna è ovviamente uguale a se stessa e quindi contiene tutti quelli. Abbiamo bisogno di trovare la colonna che ha il maggior numero di quelli iniziali , ad eccezione dell'ultima colonna, e prendere atto di tale numero di quelle iniziali, m. (In questo caso è la seconda colonna, che contiene m=3quelle iniziali). A tal fine, calcoliamo il prodotto cumulativo di ogni colonna:

1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1
0 1 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1

quindi la somma di ogni colonna

1 3 1 2 1 2 1 8

e quindi ordinare in modo non crescente e prendere il secondo valore, che è 3. Questo è il desiderato m, che indica quanti resti dobbiamo selezionare.

Q:q    % take input n implicitly. Generare row array [0 1 ... n]
tQ!    % duplicate. Transform into column array [1; 2; ...; n-1]
\      % modulo, element-wise with broadcast. Gives the 2D array
t0Z)   % duplicate. Take last column
tb     % duplicate, bubble up
=      % test for equality, element-wise with broadcast
Yp     % cumumative product of each column
s      % sum of each column. This gives the number of initial coincidences
SP2)   % sort in decreasing order and take second value: m
:Q     % generate range [2 3 ... m+1]
)      % apply as index into array of remainders of n. Implicitly display

4

Gelatina , 13 11 byte

r¬µ%€R‘$ḟ/Ṫ

Questo non vincerà alcun punto velocità brownie ... Provalo online! oppure verifica i casi di test più piccoli .

Come funziona

r¬µ%€R‘$ḟ/Ṫ  Main link. Argument: n

r¬           Range from n to (not n).
             This yields [n, ..., 0] if n > 0 and [0, 1] otherwise.

  µ          Begin a new, monadic chain. Argument: A (range)

       $     Combine the previous two links into a monadic chain:
     R         Range; turn each k in A into [1, ..., k] or [] if k == 0.
      ‘        Increment to map k to [2, ..., k+1].
   %€        Take each k in A modulo all the integers in the 2D list to the right.
        ḟ/   Reduce by filter-not; sequentially remove all remainder sequences of
             n-1, ..., (not n) from the remainder sequences of n.
          Ṫ  Tail; take the last remainder sequence.
             This gives the shortest sequence for descending A and the longest one
             (i.e., [0]) for ascending A.

Perché hai incluso due risposte ???
Erik the Outgolfer,

Perché sono due approcci completamente diversi. Mentre questo è più corto di 3 byte, l'altro è in realtà abbastanza veloce da calcolare tutti i casi di test.
Dennis,

Se fossi in te, non l'avrei fatto ... se non fosse stato un voto positivo / negativo.
Erik the Outgolfer,

Lingue / approcci diversi vanno in risposte diverse. Questa è stata la mia prima meta domanda.
Dennis,

3

Python 3.5, 117 95 78 byte

import sympy
r=lambda n,m=2,M=1,*l:M>n and l or r(n,m+1,sympy.lcm(m,M),*l,n%m)

Richiede Python 3.5 e sympy ( python3 -m pip install --user sympy). Ringraziamo @Dennis per informarmi che Python 3.5 consente il *ltrucco con argomenti predefiniti.


Con SymPy 0.7.5, è possibile abbreviare M>n and la l*(M>n).
Dennis,

3

Python 2, 73 70 69 65 byte

i=l=1
n=input()
while l<=n|1:
 i+=1;a=l;print n%i
 while l%i:l+=a

Un programma completo. @Dennis ha salvato 4 byte migliorando il modo in cui viene gestito lo zero.


3

Haskell, 66 60 51 50 byte

f i=mod i<$>[2..2+sum[1|l<-scanl1 lcm[2..i],l<=i]]

Esempio di utilizzo: f 42-> [0,0,2,2]. È l'algoritmo descritto nella risposta di @Martin Büttner .

Terrò la versione precedente come riferimento, perché è piuttosto veloce:

Haskell, 51 byte

f i=mod i<$>[[2..x]|x<-[2..],foldl1 lcm[2..x]>i]!!0

Ci vogliono 0,03 secondi per f (10^100)il mio laptop di cinque anni.

Modifica: @xnor ha trovato un byte da salvare. Grazie!


Salvataggio di un byte contando gli indici fino a quando l'mcm diventa troppo alto:h i=mod i<$>[2..2+sum[1|l<-scanl1 lcm[2..i],l<=i]]
xnor

2

Pyth, 51 byte 66 byte

IqQZ[Z).q)IqQ1[1))IqQ2,0 1))FdhhQJu/*GHiGHtUd1I>JQVQ aY%QhN)<tYd.q

Provalo!

Versione a 39 byte a velocità molto più elevata (non funziona per 0-2):

FdhhQJu/*GHiGHtUd1I>JQVtd aY%QhN)<tYd.q

Sembra funzionare per numeri assurdamente grandi come 10 10 3

Nota: questa risposta non funziona per 0, 1 e 2. Risolto!


2

JavaScript (ES6), 81 77 byte

f=(n,r=[n%2],l=i=2,g=(j,k)=>j?g(k%j,j):k)=>l>n?r:f(n,[...r,n%++i],i/g(i,l)*l)

Ciò crea ricorsivamente la risposta fino a quando l'LCM non supera il numero originale. Naturalmente anche il GCD viene calcolato in modo ricorsivo.

Modifica: salvato 4 byte grazie a @ user81655.


@ user81655 È appena subdolo ...
Neil,

2

Rubino, 52 byte

->n{m=t=1;a=[];(a<<n%m)until n<t=t.lcm(m+=1);a<<n%m}

Questa soluzione controlla ogni possibile a mpartire da 2 che è il resto che rende unica la sequenza. Ciò che rende l'ultimo munico non è il resto stesso, ma che mè l'ultimo membro dell'intervallo più piccolo in (2..m)cui il minimo comune multiplo (LCM) di quell'intervallo è maggiore di n. Ciò è dovuto al teorema del resto cinese, dove per determinare in modo univoco quale numero nè con un numero di resti, l'LCM di quei resti deve essere maggiore di n(se si seleziona nda (1..n); se si seleziona nda a..b, l'LCM deve essere solo maggiore di b-a)

Nota: ho inserito a<<n%malla fine del codice perché i until n<t=t.lcm(m+=1)cortocircuiti precedenti ahanno ricevuto l'ultimo elemento per renderlo unico.

Se qualcuno ha qualche suggerimento sul golf, per favore fatemi sapere nei commenti o nella chat PPCG .

Ungolfing:

def remainder_sequence(num)
  # starting with 1, as the statements in the until loop immediately increments divisor
  divisor = 1
  # starts with 1 instead of 2, as the statements in the until loop
  # immediately change product to a new lcm
  product = 1
  remainders = []

  # this increments divisor first then checks the lcm of product and divisor
  # before checking if num is less than this lcm
  until num < (product = product.lcm(divisor = divisor + 1))
    remainders << num % divisor
  end

  # until always short circuits before the last element is entered
  # so this enters the last element and returns
  return remainders << num % divisor
end


1

Python 3.5, 194 181 169 152 149 146 byte:

( Grazie a @ Sherlock9 per 2 byte! )

def r(o,c=0):
 y=[[j%i for i in range(2,100)]for j in range(o+1)]
 while 1:
  c+=1;z=y[-1][:c]
  if z not in[f[:c]for f in y[:-1]]:break
 print(z)

Funziona perfettamente ed è anche abbastanza veloce. Calcolo per la sequenza minima rimanente di 100000uscite [0, 1, 0, 0, 4, 5, 0, 1, 0, 10, 4, 4]e ha impiegato solo circa 3 secondi. È stato anche in grado di calcolare la sequenza per l'input 1000000(1 milione), l'output [0, 1, 0, 0, 4, 1, 0, 1, 0, 1, 4, 1, 8, 10, 0, 9]e ha impiegato circa 60 secondi.

Spiegazione

Fondamentalmente ciò che fa questa funzione è innanzitutto creare un elenco, ycon tutto j mod idove si jtrova ogni numero intero nell'intervallo 0=>7(incluso 7) ed iè ogni numero intero nell'intervallo 0=>100. Il programma va quindi in un whileciclo infinito e confronta lo stesso numero di contenuti di ciascuna lista secondaria dalla prima alla penultima lista di y( y[:-1:]) con lo stesso numero di voci nell'ultima y[-1]lista secondaria ( ) dell'elenco y. Quando l'elenco secondario y[-1]è diverso da qualsiasi altro elenco secondario, il ciclo viene interrotto e viene restituita la sequenza di residui minima corretta.

Ad esempio, se l'input è 3, ysarebbe:

[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]]

Quindi, quando entra nel ciclo while, confronta ciascun elenco secondario nell'elenco y[:-1:]con lo stesso numero di elementi nell'elenco secondario y[-1]. Ad esempio, prima confronta [[0],[1],[0]]e [1]. Dal momento che l'ultimo elenco secondario è nel resto di y, continuerà su e quindi confrontare [[0,0],[0,1],[0,2]]e [1,0]. Poiché [1,0]ora NON si trova nel resto di y quell'ordine specifico , questa è la sequenza di promemoria minima e, pertanto, [1,0]verrebbe restituita correttamente.


Per salvare byte, y[:c:]è lo stesso diy[:c]
Sherlock9

0

C89, 105 byte

g(a,b){return b?g(b,a%b):a;}main(n,m,M){scanf("%d",&n);for(m=M=1;(M=++m*M/g(m,M))<=n;)printf("%d ",n%m);}

Compila (con avvertenze) usando gcc -std=c89. Prende un singolo numero su stdin e genera la sequenza di resti separati da spazi su stdout.


1
Questo non stampa nulla quando n = 0
xsot

0

C, 89 byte

a,i=2;main(l,n){for(n=atoi(gets(n))?:!puts(n);n/l;printf("%d ",n%i++))for(a=l;l%i;l+=a);}

Compilare con gcc. Provalo online: n = 59 , n = 0 .

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.