Modi per specificare la generazione casuale nelle sfide


16

Nota : in base al consenso su Meta , qui sono presenti domande su come .

Alla luce di questa "cosa da evitare quando si scrivono sfide" , ho iniziato a pensare alle sfide che coinvolgono la generazione casuale di determinati tipi di oggetti.

A volte capita che voglio pubblicare una sfida di che prevede la generazione casuale di un foo, dove

  1. è molto facile controllare se una determinata cosa è un foo, e
  2. è un po 'più difficile generare rapidamente un foo casuale "di buona qualità".

Ad esempio, un foo potrebbe essere una matrice binaria in cui non ci sono segmenti di 4 bit uguali in qualsiasi direzione. È facile controllare se una data matrice binaria è un foo, ma generare un foo casuale con una distribuzione ben distribuita sembra richiedere un algoritmo di backtracking o qualcosa di simile.

Ad ogni modo, ora dovrò specificare obiettivamente ciò che si qualifica come un foo casuale, e mi piacerebbe che fosse "imprevedibile", nel senso intuitivo che quando eseguo il programma più volte, i risultati sembrano sempre diversi. L'approccio più restrittivo è richiedere che l'output sia uniformemente casuale: tutti i foo validi hanno la stessa probabilità di essere generati. Questo di solito è troppo restrittivo, perché non ho idea di come salvarlo per generare tutti i pieni validi, rimuovere i duplicati e sceglierne uno, che è noioso e lento.

La mia prossima idea è di richiedere che tutte le persone valide abbiano una probabilità positiva di essere generate. Tuttavia, questo significa che il seguente approccio è valido: genera una cosa casuale simile a un foo (nel nostro esempio, una matrice binaria casuale), se è un foo allora restituiscilo, altrimenti restituisci un foo hardcoded (diciamo, la matrice identità ). Anche questo è un po 'noioso, dal momento che è fondamentalmente solo un riconoscimento di foos attaccato a un generatore di matrici casuali.

Potrebbe esserci una bella definizione generale per un ragazzo imprevedibilmente casuale?

TL; DR

Esiste un buon modo per specificare un oggetto "imprevedibile" generato casualmente che non risolve la distribuzione ma scoraggia l'hard-coding?


Abbiamo una definizione standard per meta su casuale che vieterebbe l'hard-coding, ma non la limiterebbe fino a quando non sarà perfettamente uniforme.
Geobits il

5
Ottima domanda Ho scoperto in passato che specificare la casualità è difficile . Soprattutto per lo scenario che descrivi, c'è anche il problema che puoi semplicemente generare candidati casuali e ripetere se non sono validi. Ciò ti dà persino una distribuzione uniforme, ma un runtime non deterministico. Quando si specifica una distribuzione uniforme c'è anche il problema che le soluzioni reali non sono mai perfettamente uniformi. Questo è un problema molto sottile. +1
Martin Ender,

@MartinEnder Giusto, ho dimenticato quell'approccio. Posso impedirlo e l'altro lento algoritmo con limiti di tempo, ma consentono comunque la soluzione "un solo hard-coded foo".
Zgarb,

sembra che potresti specificare KR / K4 CPRNG, la maggior parte delle lingue avrà una libreria en.wikipedia.org/wiki/Pseudorandom_number_generator
Ewan

1
@Zgarb un grosso problema nel non consentire "Genera e ripristina" è che la maggior parte delle librerie RNG del linguaggio fa proprio questo.
Nathan Merrill,

Risposte:


5

Ritorna mille diversi foos

Ciò rende impossibile restituire valori codificati e avere un golf decente. Tuttavia, un generatore di foo legittimo ha una piccola possibilità di emettere foo duplicati a meno che non li stia effettivamente controllando. Per rimuovere l'onere del controllo, un tasso di fallimento empiricamente testato, diciamo il 10%, potrebbe essere specificato come accettabile.

Sii consapevole del paradosso del compleanno , che la probabilità di duplicati potrebbe essere maggiore di quanto pensi. Se ci sono solo un milione di possibili foos, un migliaio di foos casuali avrà una probabilità di circa 0,6 che ci sia un duplicato lì dentro da qualche parte, e questo presuppone che la generazione di foo sia completamente uniforme. Se questo potrebbe essere un problema, richiedi diciamo 900 foos unici per ogni 1000 generati, che è molto più generoso per un vero generatore di foo ma ancora poco pratico per l'hardcoding.

Questo ti permette anche di generare ripetutamente cose simili a quelle dei foo e controllare le fooness fino a quando non ottieni foos. Penso che questa sia una soluzione valida, ma se non ti piace:

Fallo velocemente

Le probabilità che una cosa simile a un foo sia completamente casuale sono probabilmente piuttosto basse, quindi specificare un limite di tempo probabilmente forzerà un vero tentativo di generazione di foo.

Per compensare le differenze di velocità tra le diverse lingue, potresti avere limiti di tempo diversi a seconda della lingua come Hackerrank: https://www.hackerrank.com/environment . Tuttavia, se specifichi foo abbastanza grandi, la probabilità che cose foo-like casuali siano foo potrebbe essere davvero bassa, quindi una regola "prima della morte per caldo dell'universo" potrebbe essere sufficiente.


Penso che tu abbia qualcosa qui. "L'esecuzione del programma N volte non produrrà duplicati almeno il 90% delle volte" è concreta e abbastanza facile da testare e può essere combinata con un limite di tempo per impedire la forzatura bruta e anche un semplice campionamento del rifiuto.
Zgarb,

2

Non pretendo di avere la soluzione definitiva al problema (o che questa lista è esaustiva), ma voglio delineare alcuni possibili approcci che vengono in mente e perché dovrebbero o non funzionerebbero. Inoltre, non affronterò questioni tangenziali come se l'utilizzo del timestamp corrente come fonte di casualità sia sufficientemente "imprevedibile" e come applicare determinate proprietà della distribuzione della probabilità - mi concentrerò solo sull'evitare soluzioni che utilizzano hardcoding.

Non una soluzione: non consentire esplicitamente l'hard-coding

Questa è una cattiva idea. È un requisito non osservabile (il che significa che non è possibile determinare se è soddisfatto solo eseguendo il programma), che è fortemente scoraggiato su PPCG e può essere assolutamente impossibile se si esegue il programma su qualsiasi altra piattaforma, in cui gli invii sono verificati in un modo automatizzato. Il problema con un requisito come questo è che dovresti iniziare trovando una definizione obiettiva per "hard-coding". In generale, se ci provi, peggiorerai le cose.

Rendere impossibile la codifica effettiva

Se non riesci a impedirlo completamente, ma non vuoi che le persone lo usino, puoi provare a progettare la sfida in modo tale che l'hard-coding non sia semplicemente un approccio competitivo. Ciò è possibile se gli oggetti che devono essere generati sono sufficientemente grandi e incomprimibili che inserire un esempio nel codice richiederebbe molti più byte rispetto alla scrittura di un algoritmo che genera soluzioni valide in modo casuale. Nel tuo esempio specifico, ovviamente non è così, perché le matrici di identità sono valide e generalmente facili da generare, ma per altri problemi potrebbe non essere così. Se gli oggetti target sono sufficientemente irregolari, è sufficiente che siano di grandi dimensioni, il che probabilmente non influirà sul conteggio dei byte di un algoritmo reale ma farà saltare in aria la parte codificata.

Parametrizzare l'uscita

Spesso, questi problemi hanno uno o più parametri naturali, come la dimensione della matrice nel tuo esempio. In tal caso, rendere quel parametro un input può essere sufficiente per rendere impossibile o almeno impraticabile la codifica hardware. In alcuni casi, potrebbe essere facile codificare una soluzione specifica per un determinato valore di parametro che è stato trovato manualmente o tramite una ricerca approfondita, ma forse non esiste un semplice modulo chiuso per un'istanza di queste soluzioni in generale, quindi non è possibile generare facilmente un valore predefinito per input arbitrari. Ancora una volta, questo non è il caso dell'esempio che citi, perché la matrice identità funziona a qualsiasi dimensione, ma una soluzione ottimale per questo problema correlatodi solito è altamente irregolare, quindi non è possibile avere un valore predefinito senza cercare attivamente valori validi comunque. È possibile combinare questo con un limite di tempo per evitare una ricerca della forza bruta per un valore predefinito.

Metti qualche limitazione sulla distribuzione di probabilità

Se sei disposto a rinunciare a una distribuzione di probabilità completamente illimitata, puoi mettere alcuni vincoli su di essa, che ancora danno ai rispondenti molta libertà nella scelta della loro distribuzione ma che rendono difficile o impossibile la codifica hard:

  • Il vincolo più semplice che viene in mente è quello di richiedere la differenza tra la probabilità minima e massima affinché qualsiasi output possibile sia inferiore a una determinata soglia. Un approccio hard-coded avrà probabilmente probabilità quasi zero per quasi tutte le uscite e una probabilità prossima a 1 per il valore predefinito. Se si richiede che la differenza massima sia inferiore a 0,1, è necessario che ci siano 10 valori predefiniti (scelti casualmente) per rendere l'approccio un'opzione. Allo stesso modo potresti anche richiedere solo una probabilità minima per ogni possibile uscita, ad esempio 1 / (2 * N *), dove N è il numero di possibili uscite.
  • In alternativa, è possibile richiedere che non vi siano lacune (verosimili) nella distribuzione, in modo che non vi siano intervalli di dimensione δ (scelti da te) in modo tale che esistano probabilità sia superiori che inferiori. Ciò significa che non ci possono essere valori anomali in termini di probabilità, che sono probabilmente generati da un approccio codificato.

Il problema principale di questi approcci è che sono molto più difficili da ragionare, è difficile dimostrare la correttezza delle risposte e verificare sperimentalmente la correttezza può essere impossibile per ampi spazi di output. Tuttavia, forniscono un requisito principalmente osservabile per il programma che può rendere impossibile l'hardcoding.

Questi approcci possono anche richiedere un limite di tempo, perché un modo per aumentare la probabilità dei valori non predefiniti sarebbe quello di tentare di trovare un foo casuale più volte prima di tornare al valore predefinito.

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.