Come progettare una funzione che richiede una data e fornisce un numero compreso tra 1 e 6, sempre uguale per tutte le date

4

Come parte di un algoritmo che sto facendo ho bisogno di fare una funzione che prende la data corrente su una funzione e fornisce un numero compreso tra 1 e 6, e non lo stesso numero per due date consecutive. E dovrebbe sempre restituire lo stesso numero per una determinata data.

Una soluzione semplice sarebbe quella di rendere lunedì 1, martedì 2, mercoledì 3, ecc., ma dal momento che abbiamo solo 6 valori diamo nuovamente domenica 3. E poi il prossimo lunedì 1.

Il problema con questo algoritmo è che è davvero prevedibile. Un buon algoritmo dovrebbe essere più difficile da indovinare per gli altri.

Qualche consiglio su come affrontarlo?

    
posta bogen 08.01.2016 - 11:02
fonte

4 risposte

5

Un compromesso tra gli approcci di Bent e Doc Brown potrebbe essere quello di prendere il modulo Julian Date di un multiplo di 6 (ad es. 36), quindi cerca il valore corrispondente (tra 1 e 6) in una lista quasi casuale che soddisfi il "vincolo consecutivo".

Per 36, tale elenco potrebbe essere:

 246531451362532614364125615343123456

che corrisponde all'ordine delle parole finali in un Sestina (con i versi invertiti).

    
risposta data 08.01.2016 - 12:33
fonte
3

Costruisci un hash basato sulla seguente formula ...

2 A(d) + B(d) + 1

A (d) è un hash della data nell'intervallo compreso tra 0 e 2.

B (d) è il bit meno significativo di una rappresentazione del numero del giorno della data.

Poiché i valori consecutivi di 2 A (d) non differiscono mai esattamente di 1 (o di qualsiasi numero dispari), e poiché i valori consecutivi di B (d) differiscono sempre di 1, i valori consecutivi del risultato combinato non sono mai uguali.

Il modo più semplice per calcolare una A (d) imprevedibile adatta è probabilmente utilizzare un algoritmo di hash standard, ma prendere il risultato modulo 3. Gli algoritmi di hash generalmente danno un risultato nell'intervallo 0 .. (2 ^ n) -1 (o per aritmetica firmata, -2 ^ (n-1) .. (2 ^ (n-1)) - 1). Se hai degli hash firmati, assicurati di utilizzare un modulo / resto che non dia mai risultati negativi, o di correggere per quello. Modulo originale o resto per arrotondamento divisione all'infinito negativo, fornire sempre risultati non negativi. I rimanenti per gli altri schemi di arrotondamento delle divisioni, come lo schema comune di "troncamento" (verso zero), potrebbero richiedere controlli per correggerlo. C e C ++ lasciano definito lo schema di arrotondamento della divisione definito dall'implementazione, quindi il comportamento resto / modulo per i valori negativi è definito in modo simile all'implementazione.

C'è un piccolo pregiudizio usando modulo per convertire in un intervallo di 0..2, ma ciò è inevitabile - 2 ^ n valori di dominio distinti non possono essere equamente condivisi per valori di 3 intervalli. Il bias sarà piccolo, tuttavia, se n è qualcosa che probabilmente vedrai in pratica (32 o 64 bit).

    
risposta data 08.01.2016 - 13:46
fonte
2

Produce il numero in due passaggi:

  • Passaggio 1: assicurati che nessuna data consecutiva abbia lo stesso numero
  • Passaggio 2: difficoltà a indovinare

Per il passaggio 1, scegli un numero di serie per ciascuna data (ad esempio il numero di giorni dall'1.1.2000). Se questo numero è pari, lasciare che il risultato sia pari, se il numero di serie è dispari lasciare che il risultato sia dispari. Questo assicura che giorni pari e dispari si alternino, quindi due giorni consecutivi non saranno mai più gli stessi.

Per essere difficile indovinare puoi scegliere qualsiasi funzione di hash sulla data che ti dà uno dei tre risultati.

n = serial(date)
if n is even:
   step1 = 1
else:
   step1 = 0

h = hash(date)
step2 = (h % 3) * 2 + 1

result = step1 + step2

in questo codice pseudo step2 è sempre dispari. Pertanto, dopo aver aggiunto step1 , ottieni un risultato con la stessa parità di n . Ciò garantisce che non si ottenga mai lo stesso risultato per giorni consecutivi.

Per nascondere il fatto che numeri pari e dispari si alternano, puoi aggiungere una permutazione alla fine (ad esempio, i risultati degli switch 3 e 4)

    
risposta data 08.01.2016 - 12:44
fonte
-7

Prova ad impostare il limite per 1-6 nella classe Random del pacchetto java util ie, Generatore di numeri casuali.

Potrebbe aiutarti

/* package whatever; // don't place package name! */

import java.util.*;
import java.lang.*;
import java.io.*;

/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        // your code goes here
        int n = 3,j=0;
        Random r = new Random();
        String a[] ={"sunday","monday","tuesday"};
        int i =r.nextInt(3)
        for(;;)
        {
         System.out.println(a[i]+""+i);
            j++;
            if(j>3)
            {
        System.exit(0);
            }
        }
   // check next int value  
   //System.out.println("Next int value: " + randomno.nextInt(6));
    }
}
    
risposta data 08.01.2016 - 11:40
fonte

Leggi altre domande sui tag