Java 7+, n = 50 in ~ 30 sec su TIO
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.Random;
class Main{
public static void main(String[] a){
int n=50;
Random randomGenerator = new Random();
int i = n+1;
int squaredN = n*n;
int[]randomIntegers = new int[i];
randomIntegers[n] = squaredN;
while(true){
for(i=n; i-->1; ){
randomIntegers[i] = randomGenerator.nextInt(squaredN);
}
Set<Integer> result = new HashSet<>();
Arrays.sort(randomIntegers);
for(i=n; i-->0; ){
result.add(randomIntegers[i+1] - randomIntegers[i]);
}
if(!result.contains(0) && result.size()==n){
System.out.println(result);
return;
}
}
}
}
La versione non golfata della mia risposta per la versione code-golf di questa sfida per ora, con solo una piccola modifica: java.util.Random#nextInt(limit)viene utilizzata al posto di (int)(Math.random()*limit)un numero intero nell'intervallo [0, n), poiché è circa il doppio più veloce .
Provalo online.
Spiegazione:
Approccio utilizzato:
Il codice è diviso in due parti:
- Genera un elenco di
nquantità di numeri interi casuali da sommare a n squared.
- Quindi controlla se tutti i valori sono univoci e nessuno è zero e se uno dei due è falso, proverà nuovamente a eseguire il passaggio 1, sciacquando e ripetendo fino a quando non si ottiene un risultato.
Il passaggio 1 viene eseguito con i seguenti passaggi secondari:
1) Genera un array di n-1quantità di numeri interi casuali nell'intervallo [0, n squared). E aggiungi 0e n squareda questo elenco. Questo è fatto in termini di O(n+1)prestazioni.
2) Quindi ordinerà l'array con l'integrato java.util.Arrays.sort(int[]), questo viene fatto in termini di O(n*log(n))prestazioni, come indicato nei documenti:
Ordina la matrice di in specificata in ordine numerico crescente. L'algoritmo di ordinamento è un quicksort sintonizzato, adattato da Jon L. Bentley e M. Douglas McIlroy "Engineering a Sort Function", Software-Practice and Experience, Vol. 23 (11) P. 1249-1265 (novembre 1993). Questo algoritmo offre n * log (n) prestazioni su molti set di dati che causano il degrado di altri quicksorts in prestazioni quadratiche.
3) Calcola la differenza tra ogni coppia. Questo elenco risultante di differenze conterrà nnumeri interi che sommano n squared. Questo è fatto in termini di O(n)prestazioni.
Ecco un esempio:
// n = 4, nSquared = 16
// n-1 amount of random integers in the range [0, nSquared):
[11, 2, 5]
// Add 0 and nSquared to it, and sort:
[0, 2, 5, 11, 16]
// Calculate differences:
[2, 3, 6, 5]
// The sum of these differences will always be equal to nSquared
sum([2, 3, 6, 5]) = 16
Quindi questi tre passaggi sopra sono abbastanza buoni per le prestazioni, a differenza del passaggio 2 e del ciclo attorno a tutto, che è una forza bruta di base. Il passaggio 2 è suddiviso in questi passaggi secondari:
1) L'elenco delle differenze è già stato salvato in a java.util.Set. Verificherà se la dimensione di questo set è uguale a n. Se lo è, significa che tutti i valori casuali che abbiamo generato sono unici.
2) E verificherà anche che non contenga alcun valore 0nel Set, poiché la sfida richiede valori casuali nell'intervallo [1, X], dove Xè n squaredmeno la somma di [1, ..., n-1], come affermato da @Skidsdev nel commento qui sotto.
Se una delle due opzioni sopra (non tutti i valori sono univoci o è presente uno zero), verrà generato un nuovo array e impostato nuovamente ripristinando il passaggio 1. Questo continua fino a quando non si ottiene un risultato. Per questo motivo, il tempo può variare abbastanza. L'ho visto finire in 3 secondi una volta su TIO per n=50, ma anche in 55 secondi una volta per n=50.
Prova di uniformità:
Non sono del tutto sicuro di come dimostrarlo completamente onesto. L' java.util.Random#nextIntuniforme è sicura, come è descritto nei documenti:
Restituisce il successivo valore pseudocasuale, distribuito uniformemente intdalla sequenza di questo generatore di numeri casuali. Il contratto generale di nextIntè che un intvalore viene generato e restituito in modo pseudocasuale. Tutti i 2 32 possibili intvalori sono prodotti con (approssimativamente) uguale probabilità.
Le differenze tra questi valori casuali (ordinati) non sono ovviamente uniformi, ma gli insiemi nel loro insieme sono uniformi. Ancora una volta, non sono sicuro di come dimostrarlo matematicamente, ma ecco uno script che metterà i 10,000set generati (per n=10) in una mappa con un contatore , dove la maggior parte dei set sono unici; alcuni ripetuti due volte; e la ricorrenza massima ripetuta è generalmente nell'intervallo [4,8].
Istruzioni per l'installazione:
Poiché Java è un linguaggio piuttosto noto con molte informazioni disponibili su come creare ed eseguire il codice Java, lo terrò breve.
Tutti gli strumenti utilizzati nel mio codice sono disponibili in Java 7 (forse anche già in Java 5 o 6, ma usiamo 7 per ogni evenienza). Sono abbastanza sicuro che Java 7 sia già archiviato, quindi suggerirei di scaricare Java 8 per eseguire il mio codice.
Considerazioni sui miglioramenti:
Vorrei trovare un miglioramento per il controllo degli zeri e verificare che tutti i valori siano univoci. Potrei verificare 0prima, assicurandomi che il valore casuale che aggiungiamo all'array non sia già presente, ma significherebbe un paio di cose: l'array dovrebbe essere un ArrayListcosì da poter usare il metodo incorporato .contains; un ciclo while dovrebbe essere aggiunto fino a quando non abbiamo trovato un valore casuale che non è ancora nella lista. Poiché il controllo dello zero è ora eseguito con .contains(0)sul set (che viene verificato solo una volta), è molto meglio che le prestazioni lo controllino in quel punto, rispetto all'aggiunta del loop con .containssull'elenco, che verrà verificato almeno nvolte , ma molto probabilmente di più.
Per quanto riguarda il controllo di unicità, abbiamo solo la nostra nquantità di numeri interi casuali che si sommano n squareddopo il passaggio 1 del programma, quindi solo così possiamo verificare se tutti sono unici o no. Potrebbe essere possibile mantenere un elenco ordinabile anziché un array e verificare le differenze tra loro, ma dubito seriamente che migliorerà le prestazioni piuttosto che inserirle in un Sete verificare se la dimensione di quel set è nuna volta.