Identificatori univoci


31

introduzione

Per definizione, gli identificatori univoci dovrebbero essere univoci. Avere identificatori multipli uguali fa sì che si recuperino dati imprevisti. Ma con i dati che arrivano contemporaneamente da più fonti, può essere difficile garantire l'unicità. Scrivi una funzione che unifica un elenco di identificatori.

Questo è forse il peggior fluff puzzle che abbia mai scritto, ma hai capito.

Requisiti

Dato un elenco di zero o più numeri interi positivi, applica le seguenti regole a ciascun numero dal primo all'ultimo:

  • Se il numero è il primo del suo genere, conservalo.
  • Se il numero è stato precedentemente rilevato, sostituirlo con il numero intero positivo più basso non trovato in nessun punto dell'intero elenco di input o di qualsiasi output esistente.

Per la soluzione:

  • La soluzione può essere un programma o una funzione.
  • L'input può essere una stringa, un array, passato come argomento o input da tastiera.
  • L'output può essere una stringa, un array o stampato sullo schermo.
  • Tutti i numeri nell'elenco di output sono distinti.

ipotesi

  • L'elenco di input è pulito. Contiene solo numeri interi positivi.
  • Un numero intero positivo ha un intervallo compreso tra 1 e 2 31 -1.
  • Sono disponibili meno di 256 MB di memoria per le variabili del programma. (Fondamentalmente, non sono ammessi array a 2.147.483.648 elementi.)

Casi test

Input:  empty
Output: empty

Input:  5
Output: 5

Input:  1, 4, 2, 5, 3, 6
Output: 1, 4, 2, 5, 3, 6

Input:  3, 3, 3, 3, 3, 3
Output: 3, 1, 2, 4, 5, 6

Input:  6, 6, 4, 4, 2, 2
Output: 6, 1, 4, 3, 2, 5

Input:  2147483647, 2, 2147483647, 2
Output: 2147483647, 2, 1, 3

punteggio

Solo un semplice codice golf. Il conteggio di byte più basso in questo momento vince la settimana successiva.


4
Aggiungi test case: 6, 6, 1, 2, 3, 4, 56, 7, 1, 2, 3, 4, 5
Adám,

2
@ Adám non dovrebbe 6, 6, ...dare 6, 1, ...?
xnor

5
@ Adám Penso che tu abbia ragione a riguardo, ma la formulazione potrebbe essere più chiara, "set" si riferisce agli elementi incontrati, a tutti gli elementi dell'elenco di input o agli elementi dell'elenco così come sono adesso?
xnor

3
@xnor Il 6, 6, 4, 4, 2, 2test case conferma l'interpretazione di Adám: l'output previsto è 6, 1, 4, 3, 2, 5e non 6, 1, 4, 2, 3, 5.
Fatalizza

2
0 conta come un numero intero positivo per questa sfida?
Luca,

Risposte:


11

Brachylog , 8 byte

{|∧ℕ₁}ᵐ≠

Provalo online!

Spiegazione

{    }ᵐ     Map on the Input:
              Input = Output…
 |            …or…
  ∧ℕ₁         …Output is in [1,+inf)
       ≠    All elements of the output must be different
            (Implicit labeling)

8

Java 8, 158 144 byte

a->{int m=0;String r="",c=",",b=r;for(int x:a)b+=x+c;for(int x:a)if(r.contains(x+c)){for(;(r+b).contains(++m+c););r+=m+c;}else r+=x+c;return r;}
  • .contains(m+c);m++)to .contains(++m+c);)per salvare 1 byte e contemporaneamente convertito in Java 8 per salvare altri 13 byte.

spiegazioni:

Provalo qui.

a->{                      // Method with integer-array parameter and String return-type
  int m=0;                //  Lowest integer
  String r="",            //  Result-String
         c=",",           //  Comma delimiter for result String
         b=r;for(int x:a)b+=x+c;
                          //  Input array as String
  for(int x:a)            //  Loop (2) over the integers in the array
    if(r.contains(x+c)){  //   If the result already contains this integer
      for(;(r+b).contains(++m+c););
                          //    Inner (3) as long as either the result-String or array-String contains the lowest integer
                          //     and raise the lowest integer before every iteration by 1
      r+=m+c;             //    Append the result with this lowest not-present integer
    }else                 //   Else:
      r+=x+c;             //    Append the result-String with the current integer
                          //  End of loop (2) (implicit / single-line body)
  return r;               //  Return the result-String
}                         // End of method

7

JavaScript (ES6), 49 byte

a=>a.map(g=(e,i)=>a.indexOf(e)-i?g(++n,-1):e,n=0)

7

Rubino , 63 byte

->a{r=*0..a.size;r.map{|i|[a[i]]-a[0,i]==[]?a[i]=(r-a)[1]:0};a}

Provalo online!

Spiegazione

->a{                                    # Anonymous function with one argument
    r=*0..a.size;                       # Numbers from 0 to array size
    r.map{|i|                           # For all numbers in range:
        [a[i]]                          #  Get array with just a[i]
              -a[0,i]                   #  Remove elements from array that are
                                        #    also in a[0..i-1]
                    ==[]?               #  Check if result is an empty array
                        a[i]=           #  If true, set a[i] to:
                             (r-a)      #   Remove elements from number range
                                        #     that are also in input array
                                  [1]   #   Get second element (first non-zero)
                        :0};            #  If false, no-op
                            a}          # Return modified array

6

05AB1E , 17 16 18 byte

vy¯yåi¹gL¯K¹K¬}ˆ}¯

Provalo online!

Spiegazione

v                    # for each y in input
 y                   # push y
  ¯yåi               # if y exist in global list
      ¹gL            # push [1 ... len(input)]
         ¯K          # remove any number that is already in global list
           ¹K        # remove any number that is in the input
             ¬       # get the first (smallest)
              }      # end if
               ˆ     # add to global list
                }¯   # end loop, push and output global list

Probabilmente dovrei usare riduci invece di mappa ... fammi vedere se questo aiuta
Leaky Nun

@LeakyNun: la riduzione o la mappa sono spesso la strada da percorrere :)
Emigna,


3
[6, '1', '2', '3', '4', '5', '7']. Dovrebbe dare [6, '7', '1', '2', '3', '4', '5'].
Adám,

1
@Adám: grazie per la cattura! Risolto ora :)
Emigna

6

PHP, 121 byte

<?$n=array_diff(range(0,count($g=$_GET)),$g);sort($n);$r=[];foreach($g as$v)$r[]=in_array($v,$r)?$n[++$i]:$v;print_r($r);

Versione online

allargato

$n=array_diff(range(0,count($g=$_GET)),$g); # create array of ascending values which are not in input array plus zero
sort($n); # minimize keys
$r=[];  # empty result array
foreach($g as$v) # loop input array
  $r[]=in_array($v,$r)?$n[++$i]:$v; # if value is not in result array add value else take new unique value skip zero through ++$i
print_r($r); # output result array

5

Python 2, 77 79 byte

a=input();u=[];j=1
for x in a:
 u+=[[x,j][x in u]]
 while j in u+a:j+=1
print u

Accetta input da tastiera, come [3, 3, 3, 3, 3, 3].

Tieni traccia del numero intero positivo più piccolo jnon utilizzato finora. Per ogni elemento xdell'input, output xse xnon è già stato utilizzato, altrimenti output j. Infine, aggiorna jogni volta che produci qualcosa.

EDITED: per correggere un errore nella gestione dell'input di [6, 6, 4, 4, 2, 2]. Grazie a @Rod per aver segnalato l'errore e una correzione. L'errore era che, in caso di una voce duplicata, avrebbe prodotto il numero più piccolo inutilizzato fino a quel punto nell'elenco, anche se quell'output fosse apparso successivamente nell'input. (Questo era sbagliato, come chiarito nel post e nei commenti, ma l'ho comunque incasinato in qualche modo.) Comunque, la correzione era semplicemente aggiungere l'elenco di input, aall'insieme di valori che non potevano essere emessi in quel caso.


non funziona [6,6,4,4,2,2], puoi (probabilmente) risolverlo aggiungendo +aa while j in u:->while j in u+a:
Rod

@Rod Hai ragione, errore mio. (In qualche modo l'ho ancora incasinato nonostante i commenti su questo - grazie per averlo portato alla mia attenzione - e non ho anche testato la mia soluzione abbastanza bene contro i casi di test. Imbarazzante.) OK, ho incorporato il tuo molto bello risolto e verificato rispetto ai casi di test. Grazie!
Mathmandan,

5

Haskell , 79 76 byte

MODIFICARE:

  • -3 byte: @nimi ha visto che headpoteva essere sostituito da un pattern match.

([]#)è una funzione anonima che accetta e restituisce un elenco. Usa come ([]#)[2147483647, 2, 2147483647, 2].

(?)=notElem
s#(x:y)|z:_<-[x|x?s]++filter(?(s++y))[1..]=z:(z:s)#y
_#n=n
([]#)

Provalo online!

Come funziona

  • ? è un operatore abbreviato per verificare se un elemento è assente da un elenco.
  • s#lgestisce l'elenco di numeri interi l, dato un elenco sdi numeri interi già utilizzati.
    • xè il numero intero successivo da guardare, yquelli rimanenti.
    • zè il numero intero scelto per il punto successivo. È xse xnon è un elemento di s, e il primo intero positivo né in sné in yaltrimenti.
    • (z:s)#yquindi si ricorre con l' zaggiunta all'elenco intero utilizzato.
    • n è un elenco vuoto, poiché gli elenchi non vuoti sono stati gestiti nella riga precedente.
  • La funzione principale ([]#)accetta un elenco e lo chiama #come secondo argomento e un elenco vuoto per il primo argomento.

|z:_<-[x|...]...
nimi,

4

APL (Dyalog 16.0), 34 byte

(s↑v~⍨⍳⌈/v+s←+/b←(⍳≢v)≠⍳⍨v)@{b}v←⎕

2
Deve esserci un modo migliore.
Adám,


3

C # , 135 byte


golfed

(int[] i)=>{for(int x=1,v,m=0,l=i.Length,y;x<l;x++){v=i[x];for(y=0;y<l&&v==i[x]?y<x:y<l;y++)if(i[y]==v){v=++m;y=-1;}i[x]=v;}return i;};

Ungolfed

( int[] i ) => {
   for( int x = 1, v, m = 0, l = i.Length, y; x < l; x++ ) {
      v = i[ x ];

      for( y = 0; y < l && v == i[ x ] ? y < x : y < l ; y++ )
         if( i[ y ] == v ) {
            v = ++m;
            y = -1;
         }

      i[ x ] = v;
   }

   return i;
};

Leggibile non golfato

// Takes an array of Int32 objects ( 32-byte signed integers )
( int[] i ) => {

   // Cycles through each element on the array
   //   x: Scan position, starts at the 2nd element
   //   v: Value being processed
   //   m: The next minimum value to replace
   //   l: Size of the array, to save some byte count
   for( int x = 1, v, m = 0, l = i.Length, y; x < l; x++ ) {

      // Hold the value
      v = i[ x ];

      // Re-scan the array for a duplicate value up the the current position ( 'x' ) IF
      //   ... the currently hold value hasn't been modified
      //   ... otherwise, re-scans the entire array to find a suitable value to replace
      for( y = 0; y < l && v == i[ x ] ? y < x : y < l ; y++ )

         // Check if 'v' shares the same value with other element
         if( i[ y ] == v ) {

            // Set 'v' to the minimum value possible
            v = ++m;

            // Reset the scan position to validate the new value
            y = -1;
         }

      // Set the 'v' to the array
      i[ x ] = v;
   }

   // Return the array
   return i;
};

Codice completo

using System;
using System.Collections.Generic;

namespace Namespace {
   class Program {
      static void Main( String[] args ) {
         Func<Int32[], Int32[]> f = ( int[] i ) => {
            for( int x = 1, v, m = 0, l = i.Length, y; x < l; x++ ) {
               v = i[ x ];

               for( y = 0; y < l && v == i[ x ] ? y < x : y < l ; y++ )
                  if( i[ y ] == v ) {
                     v = ++m;
                     y = -1;
                  }

               i[ x ] = v;
            }

            return i;
         };

         List<Int32[]>
            testCases = new List<Int32[]>() {
               new Int32[] { },
               new Int32[] { 5 },
               new Int32[] { 1, 4, 2, 5, 3, 6 },
               new Int32[] { 3, 3, 3, 3, 3, 3 },
               new Int32[] { 6, 6, 4, 4, 2, 2 },
               new Int32[] { 2147483647, 2, 2147483647, 2 },
            };

         foreach( Int32[] testCase in testCases ) {
            Console.WriteLine( $" Input: {String.Join( ",", testCase )}\nOutput: {string.Join( ",", f( testCase ) )}\n" );
         }

         Console.ReadLine();
      }
   }
}

Uscite

  • v1.0 - 135 bytes- Soluzione iniziale.

Gli appunti

  • Nessuna


3

R , 39 46 byte

Crea un vettore dall'input, quindi sostituisce i valori duplicati con un intervallo da 1 a un milione a cui sono stati rimossi i valori di input. Restituisce un vettore numerico. Nessun input restituirà il vettore vuoto numerico (0).

i[duplicated(i)]=(1:1e6)[-(i=scan())];i

Provalo online!

Questo genererà un avviso sulla lunghezza del vettore sostitutivo

                           i=scan()     # set i as input
                 (1:1e6)                # 1 to a million (could go higher)
                 (1:1e6)[-(i=scan())]   # without input values
  duplicated(i)                         # duplicate values in i
i[duplicated(i)]=(1:1e6)[-(i=scan())]   # set duplicate i values to reduced range vector
                                     ;i # return result

3

C, 169 byte 133 byte

input = array a, output = array modificato a

i=1,j,k,l;void f(int*a,int n){for(;i<n;i++)for(j=i-1;j>=0;j--)if(a[i]==a[j]){l=1;for(k=0;k<n;)if(l==a[k])k=l++?0:0;else k++;a[i]=l;}}

formattato

int i, j, k, l;
void f(int* a, int n)
{
    for (i = 1; i<n; i++)
        for (j = i - 1; j >= 0; j--)
            if (a[i] == a[j])
            {
                l = 1;
                for (k = 0; k<n;)
                    if (l == a[k])
                        k = l++ ? 0 : 0;
                    else
                        k++;
                a[i] = l;
            }
}

Troppi byte sprecati per questi loop. Qualcuno pensa di abbreviare il codice inventando un nuovo algoritmo (che usa meno loop)? Stavo pensando, ma non ne ho trovato uno.


2

C # 7, 116 byte

int[]f(int[]c){int j=0;int h()=>c.Contains(++j)?h():j;return c.Select((e,i)=>Array.IndexOf(c,e)<i?h():e).ToArray();}

frastagliato

int[] f(int[] c)
{
    int j = 0;
    int h() => c.Contains(++j) ? h() : j;
    return c
        .Select((e, i) => Array.IndexOf(c, e) < i ? h() : e)
        .ToArray();
}

spiegato

  • la prima occorrenza di un numero viene sempre lasciata così com'è
  • vengono tratte occorrenze consecutive di un numero [1, 2, 3, ...], saltando i valori presenti nell'input.

Versione online


2

Clojure, 72 byte

#(reduce(fn[r i](conj r(if((set r)i)(nth(remove(set r)(range))1)i)))[]%)

Una riduzione di base. Se ifinora è contenuto nell'elenco di output, prenderemo il 2 ° elemento (1 quando 0-indicizzato) dall'elenco infinito di numeri interi (range)da cui abbiamo rimosso quei numeri che sono già stati utilizzati. L'intervallo inizia da zero, quindi non possiamo prendere il primo elemento ma il secondo.


1

R, 74 byte

legge l'elenco da stdin; restituisce NULL per un input vuoto.

o=c();for(i in n<-scan())o=c(o,`if`(i%in%o,setdiff(1:length(n),o)[1],i));o

spiegazione:

o=c()                                #initialize empty list of outputs
for(i in n<-scan())                  # loop through the list after reading it from stdin
    o=c(o,                           # set the output to be the concatenation of o and
      `if`(i%in%o,                   # if we've seen the element before
           setdiff(1:length(n),o)[1] # the first element not in 1,2,...
           ,i))                      # otherwise the element
o                                    # print the output

1:length(n) può essere utilizzato poiché è garantito che non avremo mai bisogno di una sostituzione al di fuori di tale intervallo.

Provalo online!


0

Assioma, 169 byte

f a==(r:List INT:=[];for i in 1..#a repeat(~member?(a.i,r)=>(r:=concat(r,a.i));for j in 1..repeat if~member?(j,r)and(~member?(j,a)or j=a.i)then(r:=concat(r,j);break));r)

ungolf e risultato

ff(a)==
  r:List INT:=[]
  for i in 1..#a repeat
      ~member?(a.i,r)=>(r:=concat(r,a.i))
      for j in 1.. repeat
            if~member?(j,r)and(~member?(j,a) or j=a.i)then(r:=concat(r,j);break)
  r

(3) -> f([])
   (3)  []
                                                       Type: List Integer
(4) -> f([5])
   (4)  [5]
                                                       Type: List Integer
(5) -> f([1,4,2,5,3,6])
   (5)  [1,4,2,5,3,6]
                                                       Type: List Integer
(6) -> f([3,3,3,3,3,3])
   (6)  [3,1,2,4,5,6]
                                                       Type: List Integer
(7) -> f([6, 6, 4, 4, 2, 2])
   (7)  [6,1,4,3,2,5]
                                                       Type: List Integer
(8) -> f([2147483647, 2, 2147483647, 2])
   (8)  [2147483647,2,1,3]
                                                       Type: List Integer
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.