고유 식별자


31

소개

정의에 따라 고유 식별자는 고유해야합니다. 동일한 식별자가 여러 개 있으면 예기치 않은 데이터가 검색됩니다. 그러나 데이터가 여러 소스에서 동시에 도착하면 고유성을 보장하기가 어려울 수 있습니다. 식별자 목록을 고유 화하는 함수를 작성하십시오.

이것은 내가 쓴 최악의 퍼즐 보풀 일지 모르지만 아이디어를 얻습니다.

요구 사항

0 개 이상의 양의 정수 목록이 제공되면 처음부터 끝까지 각 숫자에 다음 규칙을 적용하십시오.

  • 번호가 첫 번째 종류 인 경우 유지하십시오.
  • 숫자가 이전에 발견 된 경우 전체 입력 목록 또는 기존 출력에서 ​​찾을 수없는 최저 양의 정수로 바꾸십시오.

솔루션의 경우 :

  • 해결책은 프로그램 또는 기능 일 수 있습니다.
  • 입력은 문자열, 배열, 인수로 전달 된 입력 또는 키보드 입력일 수 있습니다.
  • 출력은 문자열, 배열 또는 화면에 인쇄 될 수 있습니다.
  • 출력 목록의 모든 숫자는 고유합니다.

가정

  • 입력 목록이 깨끗합니다. 양의 정수만 포함합니다.
  • 양의 정수는 1에서 2 31 -1 사이입니다.
  • 프로그램 변수에 256MB 미만의 메모리를 사용할 수 있습니다. (기본적으로 2,147,483,648- 요소 배열은 허용되지 않습니다.)

테스트 사례

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

채점

간단한 코드 골프. 다음 주이 시간까지 가장 낮은 바이트 수가 이깁니다.


4
테스트 사례 추가 : 6, 6, 1, 2, 3, 4, 56, 7, 1, 2, 3, 4, 5
Adám

2
@ Adám 6, 6, ...포기 해서는 안 6, 1, ...됩니까?
xnor

5
@ Adám 나는 당신이 옳다고 생각하지만, 표현이 더 명확 할 수 있습니다. "설정"은 발견 된 요소, 입력 목록의 모든 요소 또는 목록의 요소를 의미합니까?
xnor

3
@xnor 6, 6, 4, 4, 2, 2테스트 케이스는 아담의 해석을 확인 : 예상 출력은 6, 1, 4, 3, 2, 5, 그리고 6, 1, 4, 2, 3, 5.
페이탈 라이즈

2
이 문제에 대해 0은 양의 정수로 간주됩니까?
Luke

답변:



8

자바 8, 158144 바이트

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++)하려면 .contains(++m+c);)1 바이트를 저장하고, 동시에 13 개의 바이트를 저장하는 자바 (8)로 변환한다.

설명 :

여기에서 시도하십시오.

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

자바 스크립트 (ES6), 49 바이트

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

7

루비 , 63 바이트

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

온라인으로 사용해보십시오!

설명

->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 바이트

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

온라인으로 사용해보십시오!

설명

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

아마 map 대신 reduce를 사용해야 할 것입니다 ... 도움이되는지 확인해 봅시다
Leaky Nun

@LeakyNun : 축소 또는지도는 종종 갈 길입니다 :)
Emigna


3
제공합니다 [6, '1', '2', '3', '4', '5', '7']. 줘야한다 [6, '7', '1', '2', '3', '4', '5'].
Adám

1
@ Adám : 캐치 주셔서 감사합니다! 지금 수정 :)
Emigna

6

PHP, 121 바이트

<?$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);

온라인 버전

넓히는

$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

파이썬 2, 77 79 바이트

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

와 같은 키보드 입력을 [3, 3, 3, 3, 3, 3]받습니다.

j지금까지 사용되지 않은 가장 작은 양의 정수를 추적하십시오 . 각 요소에 대한 x입력의 출력 x하면 x이미 별도로 출력을 사용하지 않은 경우 j. 마지막으로 j무언가를 출력 할 때마다 업데이트하십시오 .

편집 :의 실수 처리 입력을 수정합니다 [6, 6, 4, 4, 2, 2]. 실수와 수정 사항을 지적 한 @Rod에게 감사드립니다. 실수는 중복 된 항목의 경우 출력이 나중에 입력에 나타난 경우에도 목록에서 해당 지점에 사용되지 않은 가장 작은 숫자를 출력한다는 것입니다. (이것은 게시물과 의견에서 분명히 알 수 있듯이 잘못되었지만 여전히 어쨌든 엉망이었습니다.) 어쨌든 수정 사항은 입력 목록 a을 해당 경우 출력 할 수없는 값 세트에 추가하는 것 입니다.


작동하지 않는 경우 ->[6,6,4,4,2,2]+awhile j in u:while j in u+a:
Rod

@로드 당신이 맞아요, 내 실수. (어쨌든 나는 이것에 대한 의견에도 불구하고 여전히 이것을 엉망으로 만들었습니다. 내 관심을 가져 주셔서 감사합니다.) 또한 테스트 사례에 대해 솔루션을 충분히 테스트하지 못했습니다. 당황 스럽습니다.) 좋습니다. 테스트 케이스에 대해 수정하고 확인하십시오. 감사!
mathmandan

5

하스켈 , 79 76 바이트

편집하다:

  • -3 바이트 : @nimi는 head패턴 일치로 대체 될 수 있음을 보았습니다 .

([]#)목록을 가져오고 리턴하는 익명 함수입니다. 처럼 사용하십시오 ([]#)[2147483647, 2, 2147483647, 2].

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

온라인으로 사용해보십시오!

작동 원리

  • ? 요소가 목록에 없는지 확인하기위한 약식 연산자입니다.
  • s#l이미 사용 된 정수 l목록 s이 제공된 경우 정수 목록을 처리합니다 .
    • x다음으로 볼 정수 y는 나머지 정수 입니다.
    • z다음 스팟에 선택된 정수입니다. 그것은의 x경우 x의 요소가 아닌 s, 첫 번째 양의 정수에 어느 s도에 y그렇지.
    • (z:s)#y그런 다음 z사용 된 정수 목록에 추가하여 반복 합니다.
    • n 비어 있지 않은 목록은 이전 행에서 처리되었으므로 빈 목록입니다.
  • main 함수 ([]#)는 목록을 가져 와서 #두 번째 인수로 사용하고 첫 번째 인수에 대한 빈 목록을 호출합니다.

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

4

APL (Dyalog 16.0), 34 바이트

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

2
더 좋은 방법이 있어야합니다.
Adám


3

C # , 135 바이트


골프

(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;};

언 골프

( 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;
};

언 골프 가능

// 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;
};

전체 코드

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();
      }
   }
}

자료

  • V1.0 - 135 bytes- 초기 솔루션입니다.

노트

  • 없음


3

R , 39 46 바이트

입력에서 벡터를 만든 다음 복제 된 값을 입력 값이 제거 된 1에서 백만 사이의 범위로 바꿉니다. 숫자 형 벡터를 반환합니다. 입력이 없으면 빈 벡터 숫자 (0)가 반환됩니다.

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

온라인으로 사용해보십시오!

대체 벡터의 길이에 대한 경고가 표시됩니다.

                           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 바이트 133 바이트

입력 = 배열 ​​a, 출력 = 수정 된 배열 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;}}

형식화

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;
            }
}

이 루프에 너무 많은 바이트가 낭비되었습니다. 루프를 적게 사용하는 새로운 알고리즘을 개발하여 코드를 줄이려는 사람이 있습니까? 생각하고 있었지만 찾지 못했습니다.


2

C # 7, 116 바이트

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();}

들여 쓰기

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();
}

설명

  • 숫자의 첫 번째 발생은 항상 그대로 유지됩니다.
  • 연속적인 숫자 발생은 [1, 2, 3, ...]에서 입력되며 입력에있는 값을 건너 뜁니다.

온라인 버전


2

클로저, 72 바이트

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

기본 감소. i출력리스트에 포함되어 있다면 , (range)이미 사용 된 숫자를 제거한 무한 정수 목록에서 두 번째 요소 (0 색인시 1)를 가져옵니다 . 범위는 0에서 시작하므로 첫 번째 요소는 사용할 수 없지만 두 번째 요소는 사용할 수 없습니다.


1

R, 74 바이트

stdin에서 목록을 읽습니다. 빈 입력에 대해서는 NULL을 반환합니다.

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

설명:

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) 해당 범위 밖에서 교체 할 필요가 없으므로 보장 될 수 있습니다.

온라인으로 사용해보십시오!


0

공리, 169 바이트

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와 결과

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.